java网络编程-Netty

Java网络编程-Netty

[TOC]

“早熟的人通常都晚熟,骄傲的人又很急性” ——《士兵突击》

理性的人最容易陷入感性的麻烦。该来的早晚要来,逃避只是把该难受的时间延后。随着真相揭开,时间发酵,然后看透当初懦弱丑恶的自己。

自责是无用,规划协调好今后的工作和生活。

最近在忙一个网络编程的项目,其实项目从去年七月就开始忙这个项目了,不过当时一直比较消极,效率很低。看了一堆教学视频,结果啥也没记住。

索性尝试写个博客,看能不能把自己零碎的阅读拼起来。

一、网络编程的基本知识

1)OSI 模型

image-20200314120732325

虽然只是应用,但还是需要了解一下底层的模型。

应用发送消息首先是要将数据推给内核系统的协议栈。

二、套接字模型

Socket Programming in Java

套接字编程是面向连接的,故关心两点:ip地址和端口号。

从上图可以看出,socket编程的工作流程:

  1. 初始化 ServerSocket 将其bind到ip地址和端口号上,接着开启监听listen,最后阻塞到accept上等待client的连接请求。

  2. client 首先初始化 连接 Socket,接着向server端的地址和端口发起 Connection request. 此时执行TCP的三次握手(UDP用的是DatagramSocket 类。)

  3. 连接会话(session)建立,进行一切业务处理操作。

    • client向内核发起write的系统调用执行写操作,发送请求,数据从Application被拷贝到内核协议栈。
    • 协议栈将字节流通过网络设备传输到server端的内核协议栈。
    • server端通过read系统调用, 将协议栈中client 传输的数据, 拷贝到Application,进行解析,并执行业务处理后,以同样的方式写给client 进行响应。

    故,一旦连接建立,数据传输是双向的!

  4. client,server关闭连接。

    • 当client需要和server断开连接时,调用close函数。此时发生的操作是,系统内核向该连接链路上的server发送一个FIN包,server收到后执行被动关闭,
    • 此时client收到server反馈前,认为连接是正常的, 此时整个链路处于半关闭的状态。
    • 当server执行被动关闭时,也会调用close函数,此时整个链路才进入全关闭状态, 双方都会感知到连接已关闭。

webSocket地址格式: 通用地址结构(16字节),IPV4地址结构(16字节),IPV6地址结构(28字节),本地地址结构(最多110字节:本地文件无需端口,路径不同地址可变)。

HTTP,WebSocket的区别和联系:HTTP是应用层协议,基于TCP Socket实现,通常是短连接,客户端只能不断轮询从服务端获得消息。WebSocket是对HTTP的增强,利用TCP双向特性,增强服务端到客户端的传输能力,服务端可以直接推送消息到客户端。

编程实例:

File: MyServer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.io.*;  
import java.net.*;
public class MyServer {
public static void main(String[] args){
try{
ServerSocket ss=new ServerSocket(6666);
Socket s=ss.accept();//establishes connection
DataInputStream dis=new DataInputStream(s.getInputStream());
String str=(String)dis.readUTF();
System.out.println("message= "+str);
ss.close();
}catch(Exception e){System.out.println(e);}
}
}

File: MyClient.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.io.*;  
import java.net.*;
public class MyClient {
public static void main(String[] args) {
try{
Socket s=new Socket("localhost",6666);
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
dout.writeUTF("Hello Server");
dout.flush();
dout.close();
s.close();
}catch(Exception e){System.out.println(e);}
}
}

三、Netty框架

官网https://netty.io/wiki/user-guide-for-4.x.html

翻译版:http://ifeve.com/netty5-user-guide/

上面有官网,Netty是一款基于NIO(Nonblocking I/O, 非阻塞IO)的网络通信框架。基本原理推荐这篇文章:

彻底理解Netty,这一篇文章就够了

其实本来选择Netty就是为了省些事,因为它封装的功能多。(不过其实真的挺难搞的)

Netty概览:

An Netty overview giving an overview of Netty's internal design

  • Bootstrap类,处理 开始线程,打开sockets等。
  • EventLoopGroup,是一组EventGroup,多个EventGroup组合可以共享一些资源,例如线程等。
  • EventLoop , 保持不断寻找新事件的loop, 例如:来自网络sockets的输入数据,当一个event发生时,继续进行至适当的 event handler, 例如: ChannelHandler