作者:叁念
首先建立你的服务端 MySocketServer
public class MySocketServer {
private ServerSocket serverSocket;
public static void main(String[] args) {
MySocketServer server = new MySocketServer(8000);
server.start();
}
public MySocketServer(int port) {
try {
this.serverSocket = new ServerSocket(port);
System.out.println("MySocketServer服务端启动成功! 端口:" + port);
} catch (IOException exception) {
System.out.println("MySocketServer服务端启动失败!");
}
}
/**
* 开启服务端主线程,用于接收客户端连接
* 并为客户端创建其独有的新Handler处理线程,防止堵塞
*/
private void start() {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Socket client = serverSocket.accept();
new MyClientHandler(client).start();
} catch (IOException e) {
System.out.println("服务端异常!");
}
}
}
}).start();
}
}
建立专用于服务器处理客户端的Handler处理器 MyClientHandler
public class MyClientHandler {
public static final int MAX_DATA_LEN = 1024;
private final Socket socket;
public MyClientHandler(Socket socket) {
this.socket = socket;
}
public void start() {
System.out.println("新客户端接入");
new Thread(new Runnable() {
public void run() {
doStart();
}
}).start();
}
private void doStart() {
try {
InputStream inputStream = socket.getInputStream();
while (true) {
byte[] data = new byte[MAX_DATA_LEN];
int len;
while ((len = inputStream.read(data)) != -1) {
String message = new String(data, 0, len);
System.out.println("从客户端 " + socket.getLocalPort()+" 接收数据: " + message);
socket.getOutputStream().write(data);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
启动服务器你可以看到如下,说明服务器启动成功了,服务器会为每个客户端分配一个Handler来处理数据,互不干扰
接下来建立客户端 MySocketClient 来进行连接
public class MySocketClient {
private static final String HOST = "127.0.0.1";
private static final int PORT = 8000;
private static final int SLEEP_TIME = 5000;
public static void main(String[] args) throws IOException {
final Socket socket = new Socket(HOST, PORT);
new Thread(new Runnable() {
public void run() {
System.out.println("客户端启动成功!");
while (true) {
try {
String message = "Netty笔记之基本介绍与Socket联系!";
System.out.println("客户端发送数据: " + message);
socket.getOutputStream().write(message.getBytes());
} catch (Exception e) {
System.out.println("写数据出错!");
}
sleep();
}
}
}).start();
}
/**
* 线程睡眠5秒钟发送一次数据
*/
private static void sleep() {
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
启动客户端,客户端的作用就是链接服务器发送数据,我们定义了每5秒钟就像服务器发送一次数据,如下:
此时可以给发现服务器接收到消息,如下:
到这里你应该能明白作为Socket是在吗进行通讯的了,基于原生的Socket我这里写了一个简单的GUI即时聊天器,有兴趣的可以下载了解更多
网络操作抽象类,它除了包括基本的 I/O 操作,如 bind、connect、read、write 之外,还包括了 Netty 框架相关的一些功能,如获取该 Channe l的 EventLoop
当一个连接到达时,Netty 就会注册一个 Channel,然后从 EventLoopGroup 中分配一个 EventLoop 绑定到这个Channel上,在该Channel的整个生命周期中都是有这个绑定的 EventLoop 来服务的
Netty 为异步非阻塞,即所有的 I/O 操作都为异步的,因此,我们不能立刻得知消息是否已经被处理了,通过该接口的 addListener() 方法注册一个 ChannelFutureListener,当操作执行成功或者失败时,监听就会自动触发返回结果
主要是为Channel 处理 I/O 操作
Netty 中最核心的组件,它充当了所有处理入站和出站数据的应用程序逻辑的容器。
ChannelHandler 主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等,有两个核心子类 ChannelInboundHandler 和 ChannelOutboundHandler
其中 ChannelInboundHandler 用于接收、处理入站数据和事件,而 ChannelOutboundHandler 则相反
ChannelPipeline 为 ChannelHandler 链提供了一个容器并定义了用于沿着链传播入站和出站事件流的 API。
一个数据或者事件可能会被多个 Handler 处理,在这个过程中,数据或者事件经流 ChannelPipeline,由 ChannelHandler 处理。在这个处理过程中,一个 ChannelHandler 接收数据后处理完成后交给下一个 ChannelHandler,或者什么都不做直接交给下一个 ChannelHandler
当一个数据流进入 ChannlePipeline 时,它会从 ChannelPipeline 头部开始传给第一个ChannelInboundHandler ,当第一个处理完后再传给下一个,一直传递到管道的尾部。与之相对应的是,当数据被写出时,它会从管道的尾部开始,先经过管道尾部的 “最后” 一个ChannelOutboundHandler,当它处理完成后会传递给前一个 ChannelOutboundHandler