ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

TCP Server工具类,BIO阻塞和非阻塞NIO

2026/8/11 19:24:54 拓冰建站 浏览量
TCP Server工具类,BIO阻塞和非阻塞NIO

启动自定义代码的方式

WebServer Initialized Event

	//@Component//ApplicationContext context 注入//@PostConstruct//@Async@EventListener(ApplicationReadyEvent.class)@Componentpublic class TcpServerListener implements ApplicationListener<WebServerInitializedEvent> {@Overridepublic void onApplicationEvent(WebServerInitializedEvent event) {//int serverPort = event.getWebServer().getPort();// 在此处添加代码以创建和启动 TCP 服务器updateServer.startServer(8082);}}

ServerSocket

基本代码

            // 创建ServerSocket并绑定端口ServerSocket serverSocket = new ServerSocket(8080);// 启动一个新线程来接受客户端连接while (true) {try {// 接受客户端连接Socket clientSocket = serverSocket.accept();// 关闭客户端连接clientSocket.close();} catch (IOException e) {e.printStackTrace();}}

DataInputStream

	@PostConstruct@Asyncpublic void startServer() throws Exception {//开启TCP ServerServerSocket serverSocket = new ServerSocket(8082);log.info("服务端打开了 Server started on port {}", 8082);while (true) {//等待连接Socket socket = serverSocket.accept();//获取 输入流DataInputStream inputStream = new DataInputStream(socket.getInputStream());DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());log.info("服务端收到了连接:Accepted connection from client: {}", socket.getInetAddress());//读取的字节数byte[] buffer = new byte[380];//1024//真正读取到了多少个int bytesRead;//循环进行读取while ((bytesRead = inputStream.read(buffer)) != -1) {//处理二进制数据processBinaryData(buffer, bytesRead, socket, outputStream);}//循环读取,正常每次都会读取完毕inputStream.close();outputStream.close();socket.close();}//死循环接收连接}//初始化方法结束*///关闭输入流//socket.shutdownInput();//关闭输出流,关闭 Socket//socket.shutdownOutput();//关闭Socket//socket.close();

InputStreamReader 字符流

  • BufferedReader(new InputStreamReader(socket.getInputStream()))
  • new PrintWriter(socket.getOutputStream(), true)
public class TcpServer {public static void main(String[] args) {try {//连接ServerSocket serverSocket = new ServerSocket(5555);System.out.println("服务器启动,等待客户端连接...");//阻塞Socket socket = serverSocket.accept();System.out.println("客户端已连接.");//创建 输入流。读取BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//创建 输出流。写入PrintWriter out = new PrintWriter(socket.getOutputStream(), true);String message = in.readLine();System.out.println("收到客户端消息:" + message);// 解析 JSON 消息// 发送响应给客户端out.println("构建响应 JSON");// 关闭连接socket.close();serverSocket.close();} catch (IOException e) {e.printStackTrace();}}
}

NIO Selector

ServerSocketChannel

@Configuration
public class TcpServerConfig {//@Value("${tcp.ip}")//private String tcpIp;//ApplicationContext context//@PostConstruct//@Async@EventListener(ApplicationReadyEvent.class)public void startServer() {// throws IOException//异步执行//ThreadUtil.execAsync(() -> {try {//1.打开选择器Selector selector = Selector.open();//2.打开通道 serverSocketChannelServerSocketChannel channel = ServerSocketChannel.open();//3.设置非阻塞channel.configureBlocking(false);//4.绑定本机IPchannel.bind(new InetSocketAddress(tcpIp, 8082));//5.进行注册channel.register(selector, SelectionKey.OP_ACCEPT);log.info("===============Server started on port 8082===================");while (true) {//6.选择通道int readyChannels = selector.select();//校验下if (readyChannels == 0) {continue;}//7.获取所有的keySet<SelectionKey> selectedKeys = selector.selectedKeys();//8.获取迭代器Iterator<SelectionKey> keyIterator = selectedKeys.iterator();//如果存在while (keyIterator.hasNext()) {//9.获取这个keySelectionKey key = keyIterator.next();//10.如果是个连接if (key.isAcceptable()) {//11.接收这个通道SocketChannel clientSocketChannel = serverSocketChannel.accept();//12.非阻塞的clientSocketChannel.configureBlocking(false);//13.注册为可读clientSocketChannel.register(selector, SelectionKey.OP_READ);log.info("收到连接:Accepted connection from: {}", clientSocketChannel.getRemoteAddress());} else if (key.isReadable()) {//14.如果是可读,获取通道SocketChannel clientSocketChannel = (SocketChannel) key.channel();//读取数量ByteBuffer buffer = ByteBuffer.allocate(38);//1024//15.真实读取到了多少个int bytesRead = -1;try {//这里报错了,增加防护,如果没防护,这个nio就断了bytesRead = clientSocketChannel.read(buffer);} catch (Exception e) {log.info("未读取到");e.printStackTrace();}//未读取到 关闭if (bytesRead == -1) {clientSocketChannel.close();} else if (bytesRead > 0) { //读到的 > 0//读取到了buffer.flip();//读到这个字节里byte[] data = new byte[bytesRead];buffer.get(data);//处理逻辑processBinaryData(data, bytesRead, clientSocketChannel);//String message = new String(data).trim();//System.out.println("Received message: " + message);//清理buffer.clear();}//读到了}//是可读的//移除keykeyIterator.remove();}//如果存在}//死循环} catch (Exception e) {e.printStackTrace();}//}, "MyTcpServerThread").start();
}
    //有错误,往外层抛private void sendUpdateMessage(SocketChannel clientSocketChannel) {//转为bytebyte[] binaryData = hexStringToBytes("dfsfsdfdsaf");//1.申请字节ByteBuffer buffer = ByteBuffer.allocate(binaryData.length);//2.放入buffer.put(binaryData);//3. 快速翻阅,浏览buffer.flip();//3.循环是否有:剩下的,遗留的;尚未使用、解决的while (buffer.hasRemaining()) {try {//进行写入clientSocketChannel.write(buffer);log.info("发送了一次升级的消息");} catch (IOException e) {log.info("发送升级失败");e.printStackTrace();}}}