欢迎光临
我们一直在努力

Socket 到底是什么?从“网络插座”到高并发通信的全景解析

文章目录

  • 一、Socket 的本质:应用程序通往网络的“门”
    • 1. 为什么需要 Socket?
    • 2. Socket 不是协议,而是接口
  • 二、从一条消息看懂 Socket 通信流程
    • 1. 客户端 Socket
    • 2. 服务端 Socket
  • 三、IP、端口、Socket 三者到底什么关系?
    • 1. IP 定位主机
    • 2. 端口定位应用
    • 3. Socket 是通信端点
  • 四、TCP Socket:可靠连接的主角
    • 1. TCP Socket 服务端流程
      • socket:创建通信端点
      • bind:绑定地址
      • listen:进入监听状态
      • accept:接受连接
      • recv/send:收发数据
    • 2. TCP 三次握手与 Socket
  • 五、UDP Socket:不建立连接,但速度轻盈
    • 1. UDP 没有连接,但也可以通信
    • 2. UDP 的问题要应用层解决
  • 六、Socket 编程中最容易踩的坑
    • 1. TCP 是字节流,不是消息流
    • 2. 阻塞与非阻塞
    • 3. 一个连接一个线程并不总是好方案
    • 4. 端口被占用
    • 5. 连接关闭不等于资源立刻消失
  • 七、Socket 与 HTTP、WebSocket、RPC 的关系
    • 1. HTTP 基于 Socket
    • 2. WebSocket 也不是普通 Socket
    • 3. RPC 框架底层也离不开 Socket
  • 八、从代码角度看 Socket 的基本形态
    • 1. TCP 服务端伪代码
    • 2. TCP 客户端伪代码
    • 3. UDP 服务端伪代码
  • 九、为什么 Socket 是网络编程的根基?
  • 十、学习 Socket 应该建立的正确路线
    • 1. 先理解四个核心概念
    • 2. 再掌握 TCP 与 UDP 差异
    • 3. 然后理解阻塞、非阻塞和多路复用
    • 4. 最后再看框架
  • 结语:Socket 是程序世界与网络世界的接口

很多人第一次接触网络编程时,都会遇到一个看似简单、实际很核心的词:
Socket。它常被翻译成“套接字”,但这个翻译并不直观。你可能会疑惑:Socket 是协议吗?是端口吗?是连接吗?是 API 吗?为什么 TCP 编程、UDP 编程、Web 服务、即时通讯、游戏服务器、数据库连接、RPC 框架都绕不开它?

一句话概括:

Socket 是应用程序使用网络能力的编程接口,也是操作系统为网络通信抽象出来的一种端点。

它不是 TCP,也不是 HTTP,更不是某个具体服务器。它更像是应用程序和操作系统网络协议栈之间的“插座”。应用程序把数据交给 Socket,操作系统负责通过网卡、IP、TCP/UDP 等协议把数据送出去;远端机器的操作系统再通过 Socket 把数据交给对应的应用程序。

一、Socket 的本质:应用程序通往网络的“门”

1. 为什么需要 Socket?

计算机之间通信,底层非常复杂。数据要经过网卡、驱动、操作系统内核、IP 协议、TCP/UDP 协议、路由器、交换机,最后才到达另一台机器。如果每个程序都直接操作这些底层细节,网络编程会极其痛苦。

于是操作系统提供了一套统一接口,让程序员可以像读写文件一样读写网络连接。

这套接口,就是 Socket。

从程序员角度看,Socket 通常提供这些能力:

  • 创建一个通信端点;
  • 绑定 IP 和端口;
  • 监听连接;
  • 接受连接;
  • 发送数据;
  • 接收数据;
  • 关闭连接。

你写代码时调用 socket()、bind()、listen()、accept()、connect()、send()、recv(),本质上是在请求操作系统帮你完成网络通信。

2. Socket 不是协议,而是接口

这是很多初学者最容易混淆的地方。

Socket 不是 TCP,也不是 UDP。它是使用 TCP、UDP 等协议的编程接口。

可以这样理解:

概念作用
IP 负责找到哪台机器
Port 负责找到机器上的哪个应用
TCP/UDP 负责定义数据如何传输
Socket 程序使用网络协议的接口
HTTP 基于 TCP 的应用层协议

比如你写一个 Web 服务器,浏览器访问 http://example.com。表面上你用的是 HTTP,但底层通常是:

HTTP → TCP → IP → 网卡

而你的程序并不是直接操控 TCP 内核实现,而是通过 Socket API 和操作系统交互。

二、从一条消息看懂 Socket 通信流程

假设客户端要给服务器发送一句话:

Hello Server

背后的流程大致是:

服务端应用

服务端操作系统

网络

客户端操作系统

客户端应用

服务端应用

服务端操作系统

网络

客户端操作系统

客户端应用

#mermaid-svg-ghkW96yY1JTBxDaU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ghkW96yY1JTBxDaU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ghkW96yY1JTBxDaU .error-icon{fill:#552222;}#mermaid-svg-ghkW96yY1JTBxDaU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ghkW96yY1JTBxDaU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ghkW96yY1JTBxDaU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ghkW96yY1JTBxDaU .marker.cross{stroke:#333333;}#mermaid-svg-ghkW96yY1JTBxDaU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ghkW96yY1JTBxDaU p{margin:0;}#mermaid-svg-ghkW96yY1JTBxDaU .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ghkW96yY1JTBxDaU text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-ghkW96yY1JTBxDaU .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ghkW96yY1JTBxDaU .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-ghkW96yY1JTBxDaU .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-ghkW96yY1JTBxDaU .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-ghkW96yY1JTBxDaU #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-ghkW96yY1JTBxDaU .sequenceNumber{fill:white;}#mermaid-svg-ghkW96yY1JTBxDaU #sequencenumber{fill:#333;}#mermaid-svg-ghkW96yY1JTBxDaU #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-ghkW96yY1JTBxDaU .messageText{fill:#333;stroke:none;}#mermaid-svg-ghkW96yY1JTBxDaU .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ghkW96yY1JTBxDaU .labelText,#mermaid-svg-ghkW96yY1JTBxDaU .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-ghkW96yY1JTBxDaU .loopText,#mermaid-svg-ghkW96yY1JTBxDaU .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-ghkW96yY1JTBxDaU .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ghkW96yY1JTBxDaU .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-ghkW96yY1JTBxDaU .noteText,#mermaid-svg-ghkW96yY1JTBxDaU .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-ghkW96yY1JTBxDaU .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ghkW96yY1JTBxDaU .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ghkW96yY1JTBxDaU .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ghkW96yY1JTBxDaU .actorPopupMenu{position:absolute;}#mermaid-svg-ghkW96yY1JTBxDaU .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-ghkW96yY1JTBxDaU .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ghkW96yY1JTBxDaU .actor-man circle,#mermaid-svg-ghkW96yY1JTBxDaU line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-ghkW96yY1JTBxDaU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

send("Hello Server")

TCP/IP 封装数据

发送数据包

数据包到达

TCP/IP 解包

recv() 读取数据

你在代码里看到的只是 send() 和 recv(),但中间操作系统做了大量工作。

1. 客户端 Socket

客户端通常主动连接服务器。它需要知道服务器的 IP 和端口。

例如:

connect("192.168.1.10", 8080)

这表示:我要连接 192.168.1.10 这台机器上监听 8080 端口的服务。

2. 服务端 Socket

服务端一般是被动等待连接。它要先绑定一个端口,然后监听。

典型流程是:

socket → bind → listen → accept → recv/send

也就是说,服务端先告诉操作系统:“我负责 8080 端口,有连接来了交给我。”

三、IP、端口、Socket 三者到底什么关系?

很多人会把 IP、端口、Socket 混为一谈。其实三者层次不同。

1. IP 定位主机

IP 地址用于找到网络中的某台机器。

例如:

192.168.1.10
8.8.8.8

如果把网络比作城市,IP 就像门牌号,能找到某栋楼。

2. 端口定位应用

一台机器上可能同时运行很多程序:

  • Web 服务监听 80 或 443;
  • MySQL 监听 3306;
  • Redis 监听 6379;
  • SSH 监听 22;
  • 自定义服务监听 8080。

端口就是用来区分同一台机器上的不同网络应用。

如果 IP 是楼的地址,端口就是楼里的房间号。

3. Socket 是通信端点

一个 Socket 通常由以下信息参与标识:

协议 + 本地 IP + 本地端口 + 远程 IP + 远程端口

对于一个 TCP 连接,操作系统通常可以用一个“五元组”识别它:

协议类型、本地 IP、本地端口、远程 IP、远程端口

例如:

TCP
本地:192.168.1.10:8080
远程:192.168.1.20:53211

这就代表一个具体连接。

同一个服务器可以同时接收很多客户端连接,即使它们都连到服务器的 8080 端口,只要客户端 IP 或客户端端口不同,操作系统就能区分它们。

#mermaid-svg-b2IsRBCJJUFkEJux{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-b2IsRBCJJUFkEJux .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-b2IsRBCJJUFkEJux .error-icon{fill:#552222;}#mermaid-svg-b2IsRBCJJUFkEJux .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-b2IsRBCJJUFkEJux .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-b2IsRBCJJUFkEJux .marker{fill:#333333;stroke:#333333;}#mermaid-svg-b2IsRBCJJUFkEJux .marker.cross{stroke:#333333;}#mermaid-svg-b2IsRBCJJUFkEJux svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-b2IsRBCJJUFkEJux p{margin:0;}#mermaid-svg-b2IsRBCJJUFkEJux .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-b2IsRBCJJUFkEJux .cluster-label text{fill:#333;}#mermaid-svg-b2IsRBCJJUFkEJux .cluster-label span{color:#333;}#mermaid-svg-b2IsRBCJJUFkEJux .cluster-label span p{background-color:transparent;}#mermaid-svg-b2IsRBCJJUFkEJux .label text,#mermaid-svg-b2IsRBCJJUFkEJux span{fill:#333;color:#333;}#mermaid-svg-b2IsRBCJJUFkEJux .node rect,#mermaid-svg-b2IsRBCJJUFkEJux .node circle,#mermaid-svg-b2IsRBCJJUFkEJux .node ellipse,#mermaid-svg-b2IsRBCJJUFkEJux .node polygon,#mermaid-svg-b2IsRBCJJUFkEJux .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-b2IsRBCJJUFkEJux .rough-node .label text,#mermaid-svg-b2IsRBCJJUFkEJux .node .label text,#mermaid-svg-b2IsRBCJJUFkEJux .image-shape .label,#mermaid-svg-b2IsRBCJJUFkEJux .icon-shape .label{text-anchor:middle;}#mermaid-svg-b2IsRBCJJUFkEJux .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-b2IsRBCJJUFkEJux .rough-node .label,#mermaid-svg-b2IsRBCJJUFkEJux .node .label,#mermaid-svg-b2IsRBCJJUFkEJux .image-shape .label,#mermaid-svg-b2IsRBCJJUFkEJux .icon-shape .label{text-align:center;}#mermaid-svg-b2IsRBCJJUFkEJux .node.clickable{cursor:pointer;}#mermaid-svg-b2IsRBCJJUFkEJux .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-b2IsRBCJJUFkEJux .arrowheadPath{fill:#333333;}#mermaid-svg-b2IsRBCJJUFkEJux .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-b2IsRBCJJUFkEJux .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-b2IsRBCJJUFkEJux .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-b2IsRBCJJUFkEJux .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-b2IsRBCJJUFkEJux .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-b2IsRBCJJUFkEJux .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-b2IsRBCJJUFkEJux .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-b2IsRBCJJUFkEJux .cluster text{fill:#333;}#mermaid-svg-b2IsRBCJJUFkEJux .cluster span{color:#333;}#mermaid-svg-b2IsRBCJJUFkEJux div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-b2IsRBCJJUFkEJux .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-b2IsRBCJJUFkEJux rect.text{fill:none;stroke-width:0;}#mermaid-svg-b2IsRBCJJUFkEJux .icon-shape,#mermaid-svg-b2IsRBCJJUFkEJux .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-b2IsRBCJJUFkEJux .icon-shape p,#mermaid-svg-b2IsRBCJJUFkEJux .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-b2IsRBCJJUFkEJux .icon-shape .label rect,#mermaid-svg-b2IsRBCJJUFkEJux .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-b2IsRBCJJUFkEJux .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-b2IsRBCJJUFkEJux .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-b2IsRBCJJUFkEJux :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

客户端A192.168.1.21:50001

服务器192.168.1.10:8080

客户端B192.168.1.22:50002

客户端C192.168.1.23:50003

注意,服务端并不是“一个端口只能连一个客户端”。一个监听端口可以对应大量连接。

四、TCP Socket:可靠连接的主角

在大多数网络编程场景中,说 Socket,默认往往指 TCP Socket。

TCP 是面向连接、可靠传输、按序到达的协议。它适合这些场景:

  • Web 服务;
  • 数据库连接;
  • 文件传输;
  • 登录认证;
  • 支付交易;
  • RPC 调用;
  • 大多数业务系统通信。

1. TCP Socket 服务端流程

服务端大致要经历五步:

#mermaid-svg-5KGRYx84wbvk42Ld{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5KGRYx84wbvk42Ld .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5KGRYx84wbvk42Ld .error-icon{fill:#552222;}#mermaid-svg-5KGRYx84wbvk42Ld .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5KGRYx84wbvk42Ld .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5KGRYx84wbvk42Ld .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5KGRYx84wbvk42Ld .marker.cross{stroke:#333333;}#mermaid-svg-5KGRYx84wbvk42Ld svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5KGRYx84wbvk42Ld p{margin:0;}#mermaid-svg-5KGRYx84wbvk42Ld .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-5KGRYx84wbvk42Ld .cluster-label text{fill:#333;}#mermaid-svg-5KGRYx84wbvk42Ld .cluster-label span{color:#333;}#mermaid-svg-5KGRYx84wbvk42Ld .cluster-label span p{background-color:transparent;}#mermaid-svg-5KGRYx84wbvk42Ld .label text,#mermaid-svg-5KGRYx84wbvk42Ld span{fill:#333;color:#333;}#mermaid-svg-5KGRYx84wbvk42Ld .node rect,#mermaid-svg-5KGRYx84wbvk42Ld .node circle,#mermaid-svg-5KGRYx84wbvk42Ld .node ellipse,#mermaid-svg-5KGRYx84wbvk42Ld .node polygon,#mermaid-svg-5KGRYx84wbvk42Ld .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5KGRYx84wbvk42Ld .rough-node .label text,#mermaid-svg-5KGRYx84wbvk42Ld .node .label text,#mermaid-svg-5KGRYx84wbvk42Ld .image-shape .label,#mermaid-svg-5KGRYx84wbvk42Ld .icon-shape .label{text-anchor:middle;}#mermaid-svg-5KGRYx84wbvk42Ld .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5KGRYx84wbvk42Ld .rough-node .label,#mermaid-svg-5KGRYx84wbvk42Ld .node .label,#mermaid-svg-5KGRYx84wbvk42Ld .image-shape .label,#mermaid-svg-5KGRYx84wbvk42Ld .icon-shape .label{text-align:center;}#mermaid-svg-5KGRYx84wbvk42Ld .node.clickable{cursor:pointer;}#mermaid-svg-5KGRYx84wbvk42Ld .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5KGRYx84wbvk42Ld .arrowheadPath{fill:#333333;}#mermaid-svg-5KGRYx84wbvk42Ld .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5KGRYx84wbvk42Ld .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5KGRYx84wbvk42Ld .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5KGRYx84wbvk42Ld .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5KGRYx84wbvk42Ld .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5KGRYx84wbvk42Ld .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5KGRYx84wbvk42Ld .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5KGRYx84wbvk42Ld .cluster text{fill:#333;}#mermaid-svg-5KGRYx84wbvk42Ld .cluster span{color:#333;}#mermaid-svg-5KGRYx84wbvk42Ld div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5KGRYx84wbvk42Ld .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5KGRYx84wbvk42Ld rect.text{fill:none;stroke-width:0;}#mermaid-svg-5KGRYx84wbvk42Ld .icon-shape,#mermaid-svg-5KGRYx84wbvk42Ld .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5KGRYx84wbvk42Ld .icon-shape p,#mermaid-svg-5KGRYx84wbvk42Ld .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5KGRYx84wbvk42Ld .icon-shape .label rect,#mermaid-svg-5KGRYx84wbvk42Ld .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5KGRYx84wbvk42Ld .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5KGRYx84wbvk42Ld .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5KGRYx84wbvk42Ld :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

socket 创建套接字

bind 绑定IP和端口

listen 开始监听

accept 接受客户端连接

recv/send 收发数据

close 关闭连接

每一步都有明确意义。

socket:创建通信端点

socket(AF_INET, SOCK_STREAM)

这里通常包含两个关键信息:

  • AF_INET:使用 IPv4;
  • SOCK_STREAM:使用 TCP 字节流。

如果是 IPv6,可能使用 AF_INET6。如果是 UDP,通常使用 SOCK_DGRAM。

bind:绑定地址

服务端需要绑定 IP 和端口,例如:

0.0.0.0:8080

其中 0.0.0.0 表示监听本机所有网卡地址。也就是说,不管客户端通过哪个本机 IP 访问,只要端口是 8080,都可以到达这个程序。

listen:进入监听状态

listen() 表示服务端开始等待客户端连接。

它不是马上处理数据,而是告诉操作系统:这个 Socket 可以接受连接了。

accept:接受连接

当客户端连接到来时,accept() 会返回一个新的 Socket。

这里非常关键:

监听 Socket 和连接 Socket 不是同一个东西。

监听 Socket 负责“接客”,连接 Socket 负责“服务某一个具体客户端”。

可以这样理解:

监听 Socket:前台接待
连接 Socket:具体服务员

一个服务端通常只有一个监听 Socket,但可以有很多连接 Socket。

recv/send:收发数据

连接建立后,双方就可以通过 send() 和 recv() 交换数据。

TCP 是字节流,不保留消息边界。也就是说,你发送三次:

hello
world
!

对方可能一次收到:

helloworld!

也可能分几次收到:

hel
lowor
ld!

因此 TCP 编程中经常需要自己设计应用层协议,比如使用:

  • 固定长度消息;
  • 分隔符;
  • 消息头 + 消息体;
  • JSON 行协议;
  • Protobuf + 长度前缀。

2. TCP 三次握手与 Socket

TCP 连接建立前会进行三次握手。

服务端

客户端

服务端

客户端

#mermaid-svg-X4JBVPu0YUcdveEE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-X4JBVPu0YUcdveEE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-X4JBVPu0YUcdveEE .error-icon{fill:#552222;}#mermaid-svg-X4JBVPu0YUcdveEE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-X4JBVPu0YUcdveEE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-X4JBVPu0YUcdveEE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-X4JBVPu0YUcdveEE .marker.cross{stroke:#333333;}#mermaid-svg-X4JBVPu0YUcdveEE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-X4JBVPu0YUcdveEE p{margin:0;}#mermaid-svg-X4JBVPu0YUcdveEE .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-X4JBVPu0YUcdveEE text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-X4JBVPu0YUcdveEE .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-X4JBVPu0YUcdveEE .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-X4JBVPu0YUcdveEE .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-X4JBVPu0YUcdveEE .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-X4JBVPu0YUcdveEE #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-X4JBVPu0YUcdveEE .sequenceNumber{fill:white;}#mermaid-svg-X4JBVPu0YUcdveEE #sequencenumber{fill:#333;}#mermaid-svg-X4JBVPu0YUcdveEE #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-X4JBVPu0YUcdveEE .messageText{fill:#333;stroke:none;}#mermaid-svg-X4JBVPu0YUcdveEE .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-X4JBVPu0YUcdveEE .labelText,#mermaid-svg-X4JBVPu0YUcdveEE .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-X4JBVPu0YUcdveEE .loopText,#mermaid-svg-X4JBVPu0YUcdveEE .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-X4JBVPu0YUcdveEE .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-X4JBVPu0YUcdveEE .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-X4JBVPu0YUcdveEE .noteText,#mermaid-svg-X4JBVPu0YUcdveEE .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-X4JBVPu0YUcdveEE .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-X4JBVPu0YUcdveEE .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-X4JBVPu0YUcdveEE .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-X4JBVPu0YUcdveEE .actorPopupMenu{position:absolute;}#mermaid-svg-X4JBVPu0YUcdveEE .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-X4JBVPu0YUcdveEE .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-X4JBVPu0YUcdveEE .actor-man circle,#mermaid-svg-X4JBVPu0YUcdveEE line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-X4JBVPu0YUcdveEE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

TCP 连接建立

SYN

SYN + ACK

ACK

从 Socket 编程角度看:

  • 客户端调用 connect();
  • 服务端通过 accept() 获取连接;
  • 操作系统在底层完成三次握手。

程序员通常不需要手动处理 SYN、ACK,但要理解它们影响连接建立速度、超时、半连接队列等问题。

五、UDP Socket:不建立连接,但速度轻盈

UDP Socket 和 TCP Socket 不同。UDP 是无连接、不保证可靠、不保证顺序的协议。

它适合:

  • 实时音视频;
  • 在线游戏部分数据;
  • DNS 查询;
  • 局域网广播;
  • 监控上报;
  • 允许少量丢包的场景。

UDP 不需要 listen() 和 accept()。它通常是:

socket → bind → recvfrom/sendto

#mermaid-svg-OfZqgjkHolL8rIZ0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OfZqgjkHolL8rIZ0 .error-icon{fill:#552222;}#mermaid-svg-OfZqgjkHolL8rIZ0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OfZqgjkHolL8rIZ0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .marker.cross{stroke:#333333;}#mermaid-svg-OfZqgjkHolL8rIZ0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OfZqgjkHolL8rIZ0 p{margin:0;}#mermaid-svg-OfZqgjkHolL8rIZ0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .cluster-label text{fill:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .cluster-label span{color:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .cluster-label span p{background-color:transparent;}#mermaid-svg-OfZqgjkHolL8rIZ0 .label text,#mermaid-svg-OfZqgjkHolL8rIZ0 span{fill:#333;color:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .node rect,#mermaid-svg-OfZqgjkHolL8rIZ0 .node circle,#mermaid-svg-OfZqgjkHolL8rIZ0 .node ellipse,#mermaid-svg-OfZqgjkHolL8rIZ0 .node polygon,#mermaid-svg-OfZqgjkHolL8rIZ0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .rough-node .label text,#mermaid-svg-OfZqgjkHolL8rIZ0 .node .label text,#mermaid-svg-OfZqgjkHolL8rIZ0 .image-shape .label,#mermaid-svg-OfZqgjkHolL8rIZ0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-OfZqgjkHolL8rIZ0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .rough-node .label,#mermaid-svg-OfZqgjkHolL8rIZ0 .node .label,#mermaid-svg-OfZqgjkHolL8rIZ0 .image-shape .label,#mermaid-svg-OfZqgjkHolL8rIZ0 .icon-shape .label{text-align:center;}#mermaid-svg-OfZqgjkHolL8rIZ0 .node.clickable{cursor:pointer;}#mermaid-svg-OfZqgjkHolL8rIZ0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .arrowheadPath{fill:#333333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OfZqgjkHolL8rIZ0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OfZqgjkHolL8rIZ0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OfZqgjkHolL8rIZ0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OfZqgjkHolL8rIZ0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .cluster text{fill:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 .cluster span{color:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OfZqgjkHolL8rIZ0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OfZqgjkHolL8rIZ0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-OfZqgjkHolL8rIZ0 .icon-shape,#mermaid-svg-OfZqgjkHolL8rIZ0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OfZqgjkHolL8rIZ0 .icon-shape p,#mermaid-svg-OfZqgjkHolL8rIZ0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OfZqgjkHolL8rIZ0 .icon-shape .label rect,#mermaid-svg-OfZqgjkHolL8rIZ0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OfZqgjkHolL8rIZ0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OfZqgjkHolL8rIZ0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OfZqgjkHolL8rIZ0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

创建 UDP Socket

可选 bind 绑定端口

sendto 发送数据到指定地址

recvfrom 接收数据并知道来源

1. UDP 没有连接,但也可以通信

TCP 像打电话:先建立连接,再持续说话。

UDP 像寄明信片:写上地址就发出去,不保证对方一定收到,也不保证顺序。

这并不代表 UDP 低级。恰恰相反,很多高性能实时系统都使用 UDP,因为它没有 TCP 的握手、拥塞控制、重传等待等开销。

2. UDP 的问题要应用层解决

如果你用 UDP 做可靠通信,就需要自己处理:

  • 丢包重传;
  • 消息顺序;
  • 去重;
  • 超时;
  • 流量控制;
  • 拥塞控制。

这就是为什么很多系统宁愿直接用 TCP。TCP 已经帮你解决了大部分可靠传输问题。

六、Socket 编程中最容易踩的坑

1. TCP 是字节流,不是消息流

很多新手以为:

send 一次,对方 recv 一次

这是错误的。

TCP 只保证字节顺序,不保证你发送的“包”在接收方保持同样边界。因此可能出现:

  • 粘包;
  • 半包;
  • 拆包。

例如客户端连续发送:

{"name":"Tom"}
{"age":18}

服务端可能一次收到:

{"name":"Tom"}{"age":18}

也可能只收到:

{"name":"To

所以你必须设计协议格式。

常见做法是:

消息长度 + 消息内容

例如:

000012hello world!

前面 6 位表示后面消息长度。

2. 阻塞与非阻塞

默认 Socket 很多操作是阻塞的。

比如服务端调用:

accept()

如果没有客户端连接,它就会一直等待。

调用:

recv()

如果没有数据,它也可能一直等待。

这在简单程序里没问题,但在高并发服务器里会造成线程浪费。因此出现了:

  • 阻塞 IO;
  • 非阻塞 IO;
  • IO 多路复用;
  • 异步 IO;
  • Reactor 模型;
  • Proactor 模型。

3. 一个连接一个线程并不总是好方案

最简单的服务器模型是:

每来一个客户端,就创建一个线程处理

这种方式容易理解,但连接数多了会有问题:

  • 线程创建成本高;
  • 上下文切换开销大;
  • 内存占用高;
  • 几千上万连接时难以支撑。

因此高性能网络服务器通常会使用 IO 多路复用,比如 Linux 下的 epoll,Java NIO,Node.js 的事件循环,Nginx 的事件驱动模型。

#mermaid-svg-BdLMJntcMirYTy2G{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BdLMJntcMirYTy2G .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BdLMJntcMirYTy2G .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BdLMJntcMirYTy2G .error-icon{fill:#552222;}#mermaid-svg-BdLMJntcMirYTy2G .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BdLMJntcMirYTy2G .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BdLMJntcMirYTy2G .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BdLMJntcMirYTy2G .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BdLMJntcMirYTy2G .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BdLMJntcMirYTy2G .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BdLMJntcMirYTy2G .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BdLMJntcMirYTy2G .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BdLMJntcMirYTy2G .marker.cross{stroke:#333333;}#mermaid-svg-BdLMJntcMirYTy2G svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BdLMJntcMirYTy2G p{margin:0;}#mermaid-svg-BdLMJntcMirYTy2G .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-BdLMJntcMirYTy2G .cluster-label text{fill:#333;}#mermaid-svg-BdLMJntcMirYTy2G .cluster-label span{color:#333;}#mermaid-svg-BdLMJntcMirYTy2G .cluster-label span p{background-color:transparent;}#mermaid-svg-BdLMJntcMirYTy2G .label text,#mermaid-svg-BdLMJntcMirYTy2G span{fill:#333;color:#333;}#mermaid-svg-BdLMJntcMirYTy2G .node rect,#mermaid-svg-BdLMJntcMirYTy2G .node circle,#mermaid-svg-BdLMJntcMirYTy2G .node ellipse,#mermaid-svg-BdLMJntcMirYTy2G .node polygon,#mermaid-svg-BdLMJntcMirYTy2G .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BdLMJntcMirYTy2G .rough-node .label text,#mermaid-svg-BdLMJntcMirYTy2G .node .label text,#mermaid-svg-BdLMJntcMirYTy2G .image-shape .label,#mermaid-svg-BdLMJntcMirYTy2G .icon-shape .label{text-anchor:middle;}#mermaid-svg-BdLMJntcMirYTy2G .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BdLMJntcMirYTy2G .rough-node .label,#mermaid-svg-BdLMJntcMirYTy2G .node .label,#mermaid-svg-BdLMJntcMirYTy2G .image-shape .label,#mermaid-svg-BdLMJntcMirYTy2G .icon-shape .label{text-align:center;}#mermaid-svg-BdLMJntcMirYTy2G .node.clickable{cursor:pointer;}#mermaid-svg-BdLMJntcMirYTy2G .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BdLMJntcMirYTy2G .arrowheadPath{fill:#333333;}#mermaid-svg-BdLMJntcMirYTy2G .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BdLMJntcMirYTy2G .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BdLMJntcMirYTy2G .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BdLMJntcMirYTy2G .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BdLMJntcMirYTy2G .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BdLMJntcMirYTy2G .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BdLMJntcMirYTy2G .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BdLMJntcMirYTy2G .cluster text{fill:#333;}#mermaid-svg-BdLMJntcMirYTy2G .cluster span{color:#333;}#mermaid-svg-BdLMJntcMirYTy2G div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BdLMJntcMirYTy2G .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BdLMJntcMirYTy2G rect.text{fill:none;stroke-width:0;}#mermaid-svg-BdLMJntcMirYTy2G .icon-shape,#mermaid-svg-BdLMJntcMirYTy2G .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BdLMJntcMirYTy2G .icon-shape p,#mermaid-svg-BdLMJntcMirYTy2G .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BdLMJntcMirYTy2G .icon-shape .label rect,#mermaid-svg-BdLMJntcMirYTy2G .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BdLMJntcMirYTy2G .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BdLMJntcMirYTy2G .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BdLMJntcMirYTy2G :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

大量连接

事件通知机制select/poll/epoll

少量线程处理就绪事件

读取数据/写入数据/业务处理

4. 端口被占用

服务端启动失败,经常是因为端口已经被占用。

比如你的程序想监听 8080,但另一个程序已经占用了 8080,就会报错。

这时可以:

  • 换一个端口;
  • 找到占用端口的进程并关闭;
  • 检查旧进程是否未退出;
  • 设置端口复用选项,但要谨慎使用。

5. 连接关闭不等于资源立刻消失

TCP 关闭连接后,可能进入 TIME_WAIT 状态。很多人看到端口还被占用,以为程序没关干净。实际上这是 TCP 为了确保旧连接数据不会干扰新连接而设计的机制。

这也是网络编程中必须理解的一点:Socket 的生命周期不完全由应用代码决定,操作系统协议栈也会维护状态。

七、Socket 与 HTTP、WebSocket、RPC 的关系

1. HTTP 基于 Socket

HTTP 是应用层协议,通常基于 TCP Socket。

当浏览器访问网站时,本质流程大致是:

#mermaid-svg-rxVFe9G8jnNAjp2r{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rxVFe9G8jnNAjp2r .error-icon{fill:#552222;}#mermaid-svg-rxVFe9G8jnNAjp2r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rxVFe9G8jnNAjp2r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rxVFe9G8jnNAjp2r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rxVFe9G8jnNAjp2r .marker.cross{stroke:#333333;}#mermaid-svg-rxVFe9G8jnNAjp2r svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rxVFe9G8jnNAjp2r p{margin:0;}#mermaid-svg-rxVFe9G8jnNAjp2r .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r .cluster-label text{fill:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r .cluster-label span{color:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r .cluster-label span p{background-color:transparent;}#mermaid-svg-rxVFe9G8jnNAjp2r .label text,#mermaid-svg-rxVFe9G8jnNAjp2r span{fill:#333;color:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r .node rect,#mermaid-svg-rxVFe9G8jnNAjp2r .node circle,#mermaid-svg-rxVFe9G8jnNAjp2r .node ellipse,#mermaid-svg-rxVFe9G8jnNAjp2r .node polygon,#mermaid-svg-rxVFe9G8jnNAjp2r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rxVFe9G8jnNAjp2r .rough-node .label text,#mermaid-svg-rxVFe9G8jnNAjp2r .node .label text,#mermaid-svg-rxVFe9G8jnNAjp2r .image-shape .label,#mermaid-svg-rxVFe9G8jnNAjp2r .icon-shape .label{text-anchor:middle;}#mermaid-svg-rxVFe9G8jnNAjp2r .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rxVFe9G8jnNAjp2r .rough-node .label,#mermaid-svg-rxVFe9G8jnNAjp2r .node .label,#mermaid-svg-rxVFe9G8jnNAjp2r .image-shape .label,#mermaid-svg-rxVFe9G8jnNAjp2r .icon-shape .label{text-align:center;}#mermaid-svg-rxVFe9G8jnNAjp2r .node.clickable{cursor:pointer;}#mermaid-svg-rxVFe9G8jnNAjp2r .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rxVFe9G8jnNAjp2r .arrowheadPath{fill:#333333;}#mermaid-svg-rxVFe9G8jnNAjp2r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rxVFe9G8jnNAjp2r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rxVFe9G8jnNAjp2r .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rxVFe9G8jnNAjp2r .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rxVFe9G8jnNAjp2r .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rxVFe9G8jnNAjp2r .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rxVFe9G8jnNAjp2r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rxVFe9G8jnNAjp2r .cluster text{fill:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r .cluster span{color:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rxVFe9G8jnNAjp2r .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rxVFe9G8jnNAjp2r rect.text{fill:none;stroke-width:0;}#mermaid-svg-rxVFe9G8jnNAjp2r .icon-shape,#mermaid-svg-rxVFe9G8jnNAjp2r .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rxVFe9G8jnNAjp2r .icon-shape p,#mermaid-svg-rxVFe9G8jnNAjp2r .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rxVFe9G8jnNAjp2r .icon-shape .label rect,#mermaid-svg-rxVFe9G8jnNAjp2r .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rxVFe9G8jnNAjp2r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rxVFe9G8jnNAjp2r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rxVFe9G8jnNAjp2r :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

浏览器

创建 TCP Socket

连接服务器 443端口

发送 HTTP 请求

服务器返回 HTTP 响应

浏览器渲染页面

HTTP 把数据组织成请求和响应:

GET /index.html HTTP/1.1
Host: example.com

而 TCP Socket 负责把这些字节可靠地传输过去。

2. WebSocket 也不是普通 Socket

WebSocket 和 Socket 名字很像,但不是一回事。

Socket 是操作系统层面的网络编程接口。

WebSocket 是一种应用层协议,常用于浏览器和服务器之间的双向通信。它通常先通过 HTTP 握手,然后升级为 WebSocket 连接。

适合:

  • 在线聊天;
  • 实时通知;
  • 股票行情;
  • 协同编辑;
  • 网页游戏;
  • 实时看板。

3. RPC 框架底层也离不开 Socket

像 gRPC、Dubbo、Thrift、Netty、自研 RPC 框架,底层都绕不开网络通信。只不过它们把 Socket 细节封装起来了。

你调用:

userService.getUser(1001)

看起来像本地函数调用,实际上可能经历:

序列化 → 编码 → Socket 发送 → 网络传输 → 服务端解码 → 执行业务 → 返回结果

#mermaid-svg-aEsA5jja4kDa5rgK{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aEsA5jja4kDa5rgK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aEsA5jja4kDa5rgK .error-icon{fill:#552222;}#mermaid-svg-aEsA5jja4kDa5rgK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aEsA5jja4kDa5rgK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aEsA5jja4kDa5rgK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aEsA5jja4kDa5rgK .marker.cross{stroke:#333333;}#mermaid-svg-aEsA5jja4kDa5rgK svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aEsA5jja4kDa5rgK p{margin:0;}#mermaid-svg-aEsA5jja4kDa5rgK .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-aEsA5jja4kDa5rgK .cluster-label text{fill:#333;}#mermaid-svg-aEsA5jja4kDa5rgK .cluster-label span{color:#333;}#mermaid-svg-aEsA5jja4kDa5rgK .cluster-label span p{background-color:transparent;}#mermaid-svg-aEsA5jja4kDa5rgK .label text,#mermaid-svg-aEsA5jja4kDa5rgK span{fill:#333;color:#333;}#mermaid-svg-aEsA5jja4kDa5rgK .node rect,#mermaid-svg-aEsA5jja4kDa5rgK .node circle,#mermaid-svg-aEsA5jja4kDa5rgK .node ellipse,#mermaid-svg-aEsA5jja4kDa5rgK .node polygon,#mermaid-svg-aEsA5jja4kDa5rgK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aEsA5jja4kDa5rgK .rough-node .label text,#mermaid-svg-aEsA5jja4kDa5rgK .node .label text,#mermaid-svg-aEsA5jja4kDa5rgK .image-shape .label,#mermaid-svg-aEsA5jja4kDa5rgK .icon-shape .label{text-anchor:middle;}#mermaid-svg-aEsA5jja4kDa5rgK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aEsA5jja4kDa5rgK .rough-node .label,#mermaid-svg-aEsA5jja4kDa5rgK .node .label,#mermaid-svg-aEsA5jja4kDa5rgK .image-shape .label,#mermaid-svg-aEsA5jja4kDa5rgK .icon-shape .label{text-align:center;}#mermaid-svg-aEsA5jja4kDa5rgK .node.clickable{cursor:pointer;}#mermaid-svg-aEsA5jja4kDa5rgK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aEsA5jja4kDa5rgK .arrowheadPath{fill:#333333;}#mermaid-svg-aEsA5jja4kDa5rgK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aEsA5jja4kDa5rgK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aEsA5jja4kDa5rgK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aEsA5jja4kDa5rgK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aEsA5jja4kDa5rgK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aEsA5jja4kDa5rgK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aEsA5jja4kDa5rgK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aEsA5jja4kDa5rgK .cluster text{fill:#333;}#mermaid-svg-aEsA5jja4kDa5rgK .cluster span{color:#333;}#mermaid-svg-aEsA5jja4kDa5rgK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aEsA5jja4kDa5rgK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aEsA5jja4kDa5rgK rect.text{fill:none;stroke-width:0;}#mermaid-svg-aEsA5jja4kDa5rgK .icon-shape,#mermaid-svg-aEsA5jja4kDa5rgK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aEsA5jja4kDa5rgK .icon-shape p,#mermaid-svg-aEsA5jja4kDa5rgK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aEsA5jja4kDa5rgK .icon-shape .label rect,#mermaid-svg-aEsA5jja4kDa5rgK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aEsA5jja4kDa5rgK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aEsA5jja4kDa5rgK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aEsA5jja4kDa5rgK :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

客户端调用方法

序列化参数

通过 Socket 发送

服务端接收

反序列化

执行业务逻辑

返回响应

八、从代码角度看 Socket 的基本形态

下面用伪代码理解即可,不绑定具体语言。

1. TCP 服务端伪代码

server = socket(TCP)

server.bind("0.0.0.0", 8080)

server.listen()

while true:
client = server.accept()
data = client.recv()
client.send("收到:" + data)
client.close()

这个程序能接收客户端连接,但它一次只能处理一个连接。真实服务器通常会加线程池、事件循环或异步处理。

2. TCP 客户端伪代码

client = socket(TCP)

client.connect("127.0.0.1", 8080)

client.send("hello")

response = client.recv()

client.close()

客户端主动连接服务端,发送数据,读取响应,然后关闭连接。

3. UDP 服务端伪代码

server = socket(UDP)

server.bind("0.0.0.0", 9000)

while true:
data, address = server.recvfrom()
server.sendto("收到", address)

UDP 不需要 accept(),每个数据包都自带来源地址。

九、为什么 Socket 是网络编程的根基?

Socket 重要,是因为它处在非常关键的位置。

上面是应用层,下面是操作系统网络协议栈。

#mermaid-svg-S3NhZUfhkd1Weixn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-S3NhZUfhkd1Weixn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-S3NhZUfhkd1Weixn .error-icon{fill:#552222;}#mermaid-svg-S3NhZUfhkd1Weixn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S3NhZUfhkd1Weixn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S3NhZUfhkd1Weixn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S3NhZUfhkd1Weixn .marker.cross{stroke:#333333;}#mermaid-svg-S3NhZUfhkd1Weixn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S3NhZUfhkd1Weixn p{margin:0;}#mermaid-svg-S3NhZUfhkd1Weixn .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-S3NhZUfhkd1Weixn .cluster-label text{fill:#333;}#mermaid-svg-S3NhZUfhkd1Weixn .cluster-label span{color:#333;}#mermaid-svg-S3NhZUfhkd1Weixn .cluster-label span p{background-color:transparent;}#mermaid-svg-S3NhZUfhkd1Weixn .label text,#mermaid-svg-S3NhZUfhkd1Weixn span{fill:#333;color:#333;}#mermaid-svg-S3NhZUfhkd1Weixn .node rect,#mermaid-svg-S3NhZUfhkd1Weixn .node circle,#mermaid-svg-S3NhZUfhkd1Weixn .node ellipse,#mermaid-svg-S3NhZUfhkd1Weixn .node polygon,#mermaid-svg-S3NhZUfhkd1Weixn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S3NhZUfhkd1Weixn .rough-node .label text,#mermaid-svg-S3NhZUfhkd1Weixn .node .label text,#mermaid-svg-S3NhZUfhkd1Weixn .image-shape .label,#mermaid-svg-S3NhZUfhkd1Weixn .icon-shape .label{text-anchor:middle;}#mermaid-svg-S3NhZUfhkd1Weixn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-S3NhZUfhkd1Weixn .rough-node .label,#mermaid-svg-S3NhZUfhkd1Weixn .node .label,#mermaid-svg-S3NhZUfhkd1Weixn .image-shape .label,#mermaid-svg-S3NhZUfhkd1Weixn .icon-shape .label{text-align:center;}#mermaid-svg-S3NhZUfhkd1Weixn .node.clickable{cursor:pointer;}#mermaid-svg-S3NhZUfhkd1Weixn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-S3NhZUfhkd1Weixn .arrowheadPath{fill:#333333;}#mermaid-svg-S3NhZUfhkd1Weixn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-S3NhZUfhkd1Weixn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-S3NhZUfhkd1Weixn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S3NhZUfhkd1Weixn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-S3NhZUfhkd1Weixn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S3NhZUfhkd1Weixn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-S3NhZUfhkd1Weixn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-S3NhZUfhkd1Weixn .cluster text{fill:#333;}#mermaid-svg-S3NhZUfhkd1Weixn .cluster span{color:#333;}#mermaid-svg-S3NhZUfhkd1Weixn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-S3NhZUfhkd1Weixn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-S3NhZUfhkd1Weixn rect.text{fill:none;stroke-width:0;}#mermaid-svg-S3NhZUfhkd1Weixn .icon-shape,#mermaid-svg-S3NhZUfhkd1Weixn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S3NhZUfhkd1Weixn .icon-shape p,#mermaid-svg-S3NhZUfhkd1Weixn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-S3NhZUfhkd1Weixn .icon-shape .label rect,#mermaid-svg-S3NhZUfhkd1Weixn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S3NhZUfhkd1Weixn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-S3NhZUfhkd1Weixn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-S3NhZUfhkd1Weixn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

业务应用Web服务/游戏/聊天/数据库客户端

Socket API

TCP/UDP

IP

网卡驱动

物理网络

对于应用开发者来说,Socket 是你能直接操作的网络入口。你不需要亲自构造 IP 包,也不需要自己实现 TCP 重传机制。操作系统已经帮你封装好了。

但如果你完全不了解 Socket,也会遇到很多问题:

  • 为什么服务端要监听端口?
  • 为什么连接会超时?
  • 为什么数据会粘包?
  • 为什么一个端口能支持很多连接?
  • 为什么高并发不能简单开很多线程?
  • 为什么短连接很多会导致 TIME_WAIT?
  • 为什么 HTTP 服务本质上也是网络连接?

这些问题最后都绕回 Socket。

十、学习 Socket 应该建立的正确路线

1. 先理解四个核心概念

学习 Socket,不要一开始就陷入 API 细节。先理解:

IP、端口、协议、连接

这四个概念明白了,再看代码就容易很多。

2. 再掌握 TCP 与 UDP 差异

重点不是背概念,而是知道什么时候用谁。

TCP 适合可靠业务:

  • 登录;
  • 支付;
  • 数据库;
  • 文件;
  • 后台系统;
  • 普通 Web 服务。

UDP 适合实时、轻量、可容忍丢包的业务:

  • 语音;
  • 视频;
  • 游戏移动同步;
  • DNS;
  • 广播发现。

3. 然后理解阻塞、非阻塞和多路复用

这是从“能写网络程序”到“能写高并发网络程序”的分水岭。

你可以按这个顺序学习:

阻塞 Socket → 多线程服务器 → 非阻塞 Socket → select/poll/epoll → Reactor 模型

不要一开始就硬啃 epoll。先写一个最简单的 TCP echo server,再逐步优化。

4. 最后再看框架

例如:

  • Java:Socket、ServerSocket、NIO、Netty;
  • Python:socket、asyncio;
  • Go:net 包、goroutine;
  • Node.js:net、http、事件循环;
  • C/C++:BSD Socket、epoll、libevent、asio。

框架的存在不是为了替代 Socket 思维,而是为了封装复杂度。你理解了 Socket,再看 Netty、Nginx、Redis、MySQL 连接池,很多设计都会变得清晰。

结语:Socket 是程序世界与网络世界的接口

Socket 看起来只是几个 API,但它背后连接的是整个网络体系。

它向上支撑 HTTP、WebSocket、RPC、数据库连接、微服务通信;向下连接 TCP、UDP、IP、网卡和物理网络。它不是某种神秘技术,而是操作系统给应用程序提供的网络通信抽象。

真正理解 Socket 后,你会发现很多网络问题不再玄学:

  • 服务为什么要监听端口;
  • 客户端为什么要连接服务器;
  • 数据为什么会被拆分或合并;
  • 连接为什么会断开;
  • 高并发为什么需要事件驱动;
  • HTTP 为什么不是凭空存在,而是建立在 TCP Socket 之上。

所以,Socket 不是网络编程的“一个知识点”,而是进入网络世界的一扇门。学懂它,你就能从“会调接口”慢慢走向“理解通信系统”。

赞(0)
未经允许不得转载:171主机测评 » Socket 到底是什么?从“网络插座”到高并发通信的全景解析
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址