孤舟笔记 IO 与网络编程篇五 网络编程你真的懂吗?从Socket到TCP连接全解析
文章目录一、先说结论网络编程核心事实二、TCP 编程三次握手的 Socket 视角三、UDP 编程无连接的数据报四、服务端线程模型演进模型一一连接一线程最原始模型二线程池改进模型三NIO Selector最优五、TCP 连接的状态流转六、Socket 常用参数网络编程 全景回答技巧与点评标准回答加分回答面试官点评个人网站面试官问说说你对网络编程的理解很多人只能说出Socket 编程但追问TCP 和 UDP 的 Socket 有什么区别、“服务端怎么处理多连接”、“TIME_WAIT 是什么”就答不全了。网络编程是后端开发的基础功理解 Socket 才能理解上层框架。今天咱们把 Java 网络编程的核心知识讲透。一、先说结论网络编程核心事实维度说明核心 APIServerSocket SocketTCPDatagramSocketUDPTCP Socket面向连接可靠传输字节流UDP Socket无连接不可靠数据报线程模型一连接一线程 → 线程池 → NIO Selector关键状态TIME_WAIT、CLOSE_WAIT、ESTABLISHED一句话记住TCP Socket 像打电话先拨号再通话UDP Socket 像发短信直接发不管对方在不在。二、TCP 编程三次握手的 Socket 视角服务端ServerSocketservernewServerSocket(8080);// 1. 绑定端口Socketclientserver.accept();// 2. 等待连接三次握手InputStreaminclient.getInputStream();// 3. 获取输入流OutputStreamoutclient.getOutputStream();// 4. 获取输出流客户端SocketsocketnewSocket(127.0.0.1,8080);// 1. 发起连接三次握手OutputStreamoutsocket.getOutputStream();// 2. 获取输出流InputStreaminsocket.getInputStream();// 3. 获取输入流Socket 与三次握手的对应客户端 服务端 | | |──── SYN ────────────────────→| server.accept() 等待 | | |←─── SYNACK ────────────────| 三次握手建立连接 | | |──── ACK ────────────────────→| accept() 返回 Socket | | |──── 数据 ──────────────────→| 读写数据 |←─── 数据 ───────────────────|accept() 返回的 Socket 和客户端的 Socket 是一对——它们代表同一个 TCP 连接的两端。三、UDP 编程无连接的数据报// 服务端DatagramSocketservernewDatagramSocket(9090);byte[]bufnewbyte[1024];DatagramPacketpacketnewDatagramPacket(buf,buf.length);server.receive(packet);// 接收数据报 // 客户端DatagramSocketclientnewDatagramSocket();byte[]datahello.getBytes();InetAddressaddrInetAddress.getByName(127.0.0.1);DatagramPacketpacketnewDatagramPacket(data,data.length,addr,9090);client.send(packet);// 发送数据报 TCP vs UDP 对比维度TCPUDP连接面向连接三次握手无连接可靠性可靠确认重传不可靠传输方式字节流数据报顺序保证有序不保证速度较慢较快适用场景文件传输、HTTP视频直播、DNS四、服务端线程模型演进模型一一连接一线程最原始while(true){Socketclientserver.accept();newThread(()-handle(client)).start();// 每个连接一个线程 }// 问题1000 连接 1000 线程OOM模型二线程池改进ExecutorServicepoolExecutors.newFixedThreadPool(200);while(true){Socketclientserver.accept();pool.submit(()-handle(client));// 线程池复用 }// 改进限制了线程数量// 问题200 个线程都在阻塞等待浪费资源模型三NIO Selector最优SelectorselectorSelector.open();ServerSocketChannelsscServerSocketChannel.open();ssc.configureBlocking(false);ssc.register(selector,SelectionKey.OP_ACCEPT);while(true){selector.select();// 等待事件 for(SelectionKeykey:selector.selectedKeys()){if(key.isAcceptable()){// 接受新连接}elseif(key.isReadable()){// 读取数据}}}// 1~4 个线程处理成千上万个连接五、TCP 连接的状态流转TCP 连接从建立到关闭的完整状态客户端 服务端 CLOSED CLOSED | | | SYN_SENT ──── SYN ────→ LISTEN | | | | ESTABLISHED ← SYNACK ─ SYN_RCVD | | | | ──── ACK ────→ ESTABLISHED | | | | ──── FIN ────→ CLOSE_WAIT | | FIN_WAIT_1 | | | | FIN_WAIT_2 ←──── ACK ──── | | | | TIME_WAIT ←──── FIN ──── LAST_ACK | | | | ──── ACK ────→ CLOSED | | TIME_WAIT等 2MSL | | CLOSED |两个关键状态状态出现在原因解决TIME_WAIT主动关闭方等待 2MSL 确保对方收到最后的 ACKSO_REUSEADDRCLOSE_WAIT被动关闭方应用层没有调用 close()检查代码是否关闭 Socket大量 TIME_WAIT主动关闭连接的一方会进入 TIME_WAIT等待 2MSL约 60 秒。高并发短连接场景下可能导致端口耗尽。大量 CLOSE_WAIT说明应用层 Bug——对方关闭了连接但你没有调用 close()。六、Socket 常用参数// 地址复用——TIME_WAIT 状态下也能绑定同一端口server.setReuseAddress(true);// 解决 TIME_WAIT 端口占用// 关闭 Nagle 算法——小数据立即发送socket.setTcpNoDelay(true);// 适合实时性要求高的场景// Keep-Alive——检测死连接socket.setKeepAlive(true);// 超时设置socket.setSoTimeout(5000);// 读超时 5 秒server.setSoTimeout(3000);// accept 超时 3 秒// 发送/接收缓冲区大小socket.setSendBufferSize(64*1024);socket.setReceiveBufferSize(64*1024);网络编程 全景网络编程 全景 核心 API ├── TCP ── ServerSocket Socket ├── UDP ── DatagramSocket DatagramPacket └── NIO ── ServerSocketChannel SocketChannel Selector TCP vs UDP ├── TCP ── 可靠、有序、字节流、有连接 └── UDP ── 不可靠、无序、数据报、无连接 线程模型演进 ├── 一连接一线程 ── OOM ├── 线程池 ── 限制线程数但浪费资源 └── NIO Selector ── 一线程多连接 TCP 关键状态 ├── TIME_WAIT ── 主动关闭方等 2MSL ├── CLOSE_WAIT ── 被动关闭方未 close └── ESTABLISHED ── 连接建立 常用参数 ├── SO_REUSEADDR ── 地址复用 ├── TCP_NODELAY ── 关闭 Nagle ├── SO_KEEPALIVE ── 保活探测 └── SO_TIMEOUT ── 超时设置 口诀TCP 可靠三次握UDP 无连接快但丢 线程模型三级跳NIO Selector 是最优 TIME_WAIT 主动等CLOSE_WAIT 忘了关 参数设置要合理网络编程才稳定。回答技巧与点评标准回答Java 网络编程基于 Socket API。TCP 编程使用 ServerSocket 监听 Socket 通信面向连接、可靠传输UDP 编程使用 DatagramSocket 发送/接收数据报无连接、不可靠但快速。服务端线程模型经历了从一连接一线程到线程池再到 NIO Selector 的演进NIO 通过多路复用实现一线程处理多连接是高并发场景的最优方案。TCP 连接关闭时主动关闭方进入 TIME_WAIT等 2MSL被动关闭方如果没调用 close() 会停留在 CLOSE_WAIT。加分回答Netty 的线程模型Netty 采用主从 Reactor 多线程模型——boss group主 Reactor负责 accept 连接worker group从 Reactor负责 IO 读写。每个 EventLoop 是一个 Reactor内部是一个 Selector 一个任务队列。这种模型比直接用 NIO 编程简单得多性能也更好半包和粘包问题TCP 是字节流协议不保证消息边界——发送hello和world可能被接收为helloworld粘包或hel“loworld”半包。解决方案固定长度、分隔符、长度字段最常用。Netty 提供了 LengthFieldBasedFrameDecoder 开箱即用WebSocket 和 HTTP/2传统 HTTP 是短连接请求-响应模式WebSocket 在 TCP 上实现全双工通信HTTP/2 在 TCP 上实现多路复用。它们都是基于 TCP Socket 的应用层协议但通过不同的帧格式实现了更高效的通信面试官点评这道题考的是你对网络编程基础的理解。能说出ServerSocket/Socket、TCP vs UDP、线程模型演进是基本要求能讲清楚 TIME_WAIT 和 CLOSE_WAIT 的区别、NIO 的优势、常用 Socket 参数才算及格。如果你能提到 Netty 的线程模型、半包粘包问题、WebSocket/HTTP2面试官会认为你对网络编程的理解不只在 Socket API 层面还延伸到了协议和框架层面。原文阅读内容有帮助点赞、收藏、关注三连评论区等你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2605281.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!