NIO与BIO服务器端对比
创始人
2024-02-10 14:04:35
0

本文利用NIO实现一个重复回复,客户端发送什么信息,客户端就会收到什么信息。

主要是理解NIO与BIO的区别。客户端采用telnet进行测试,以下连接是Telnet安装的方法。

Telnet的简单使用_武汉小喽啰的博客-CSDN博客_telnet

注意!!!当使勇telnet连接成功到黑屏时候一定要用ctrl +] 进入客户端

注意!!!当使勇telnet连接成功到黑屏时候一定要用ctrl +] 进入客户端

注意!!!当使勇telnet连接成功到黑屏时候一定要用ctrl +] 进入客户端

可以使用?/help 进行命令查看命令很少的。

BIO即阻塞IO测试,发现以下两个地方会被阻塞,第一个客户端连接,第二个是客户端输入信息

  • Socket socket = serverSocket.accept();
  • InputStream is = socket.getInputStream();

客户端连接服务端流程:

【第一步】启动服务器--服务器运行到accept命令阻塞

【第二步】连接客户端,服务器接收客户端,阻塞到 getInputStream() 等待客户端发送信息。

可以看出来,一个线程为客户端服务,直到客户端断开连接

【代码】

package cn.msf.bio;import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** @author: msf* @date: 2022/11/22*/
public class BIO {public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(10101);System.out.println("服务端启动");while (true) {// 获取一个套接字(阻塞)Socket socket = serverSocket.accept();System.out.println("来了一个客户端");hander(socket);}} catch (IOException e) {e.printStackTrace();}}private static void hander(Socket socket) {byte[] bytes = new byte[1024];int len = 0;try {// 阻塞等待。InputStream is = socket.getInputStream();// 将信息读到bytes中。while ((len = is.read(bytes)) != -1) {System.out.println(new String(bytes, 0, len));}} catch (IOException e) {e.printStackTrace();} finally {System.out.println("关闭socket");try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}

NIO实现测试

【第一步】建立服务器端,这里使用的命令是

ServerSocketChannel serverChannel = ServerSocketChannel.open();// 设置为不阻塞
serverChannel.configureBlocking(false);// 设置socket的连接接口
serverChannel.socket().bind(new InetSocketAddress("localhost",port));

【第二步】开启selector相当找了一个服务员,为客户端服务

// 启动一个选择器selector = Selector.open();serverChannel.register(selector, SelectionKey.OP_ACCEPT);

 【第三步】监听客户端连接

 public void listen() throws IOException {System.out.println("服务端启动成功");while (true) {// 当服务端注册的时间到达后,返回;否则会一直阻塞selector.select();selector.wakeup();Iterator ite = selector.selectedKeys().iterator();while (ite.hasNext()) {SelectionKey key = ite.next();ite.remove();// 处理事件的类型handler(key);}}}

【第四步】为不同客户端处理不同的事件。

可以达到一对多服务,不会想BIO一样阻塞在getinputstream哪里只等待一个客户端

 

private void handler(SelectionKey key) throws IOException {if (key.isAcceptable()) {// 说明是注册事件handlerAccept(key);} else if (key.isReadable()) {handlerRead(key);}}

【完整代码】 

package cn.msf.nio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Iterator;/*** @author: msf* @date: 2022/11/23*/
public class NIOServer {private Selector selector;public static void main(String[] args) throws IOException {NIOServer server = new NIOServer();server.initServer(8000);server.listen();}public void initServer(int port) throws IOException {// 获得一个ServerSocket 通道ServerSocketChannel serverChannel = ServerSocketChannel.open();// 设置为不阻塞serverChannel.configureBlocking(false);// 设置socket的连接接口serverChannel.socket().bind(new InetSocketAddress("localhost",port));// 启动一个选择器selector = Selector.open();serverChannel.register(selector, SelectionKey.OP_ACCEPT);}public void listen() throws IOException {System.out.println("服务端启动成功");while (true) {// 当服务端注册的时间到达后,返回;否则会一直阻塞selector.select();selector.wakeup();Iterator ite = selector.selectedKeys().iterator();while (ite.hasNext()) {SelectionKey key = ite.next();ite.remove();// 处理事件的类型handler(key);}}}private void handler(SelectionKey key) throws IOException {if (key.isAcceptable()) {// 说明是注册事件handlerAccept(key);} else if (key.isReadable()) {handlerRead(key);}}public void handlerAccept(SelectionKey key) throws IOException {// 当有事件来了,获得之前的服务端ServerSocketChannel server = (ServerSocketChannel) key.channel();// 获得客户端的通道--相当于客户端SocketChannel channel = server.accept();channel.configureBlocking(false);System.out.println("客户端连接");channel.register(this.selector,SelectionKey.OP_READ);}private void handlerRead(SelectionKey key) throws IOException {// 服务器可读消息,得到事件发生的Socket通道。SocketChannel channel = (SocketChannel) key.channel();// 创建缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);int read = channel.read(buffer);if (read > 0) {byte[] data = buffer.array();String msg = new String(data).trim();System.out.println("服务器收到消息: " + msg);ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));// 将消息发送给客户端channel.write(outBuffer);} else {channel.close();}}
}

相关内容

热门资讯

国联政信申请智能法律调解全流程... 金融界2025年8月22日消息,国家知识产权局信息显示,北京国联政信科技有限公司申请一项名为“智能法...
这项育儿补贴政策明确了! 新理财2025-08-22 16:28:03 关于育儿补贴有关个人所得税政策的公告 财政部 税务...
济南超市突然大量出现,不少人尝... 今年夏天,白桦树汁成为不少饮料巨头企业竞逐的网红单品,农夫山泉母公司养生堂、汇源等纷纷推出相关饮品,...
曼联重磅转会在即,鲁本·阿莫林... 随着夏季转会窗口接近尾声,曼联在这场转会博弈中又将掀起怎样的波澜?红魔正在积极寻找新中场,力图在最后...
打虎!正部级王莉霞,任上被查 编辑|余晖 内蒙古自治区党委副书记、自治区政府主席王莉霞涉嫌严重违纪违法,目前正接受中央纪委国家监...
卖人必赔!ESPN:爵爷退休后... 直播吧08月22日讯 距离英超夏窗关闭还有10天时间,曼联“炸弹小队”还有多名球员滞销。 拉什福德以...
江西赣锋锂业集团发布对外担保制... 2025-08-22,江西赣锋锂业集团股份有限公司发布对外担保制度公告。 该制度旨在保护投资者权益,...
上海市委中心组学习会专题学习《... 上海市委中心组学习会今天(8月22日)上午举行,听取华东师范大学特聘教授、党章研究中心主任周敬青所作...
市委中心组学习会专题学习《中国... 市委中心组学习会今天上午举行,听取华东师范大学特聘教授、党章研究中心主任周敬青所作的“学习贯彻巡视工...