Linux网络编程深度解析:从Socket API到自定义协议设计

哈喽,编程搭子们!😜 又到了沉浸式敲代码的快乐时间~把生活调成「代码模式」,带着满满的热爱钻进编程的奇妙世界------今天也要敲出超酷的代码,冲鸭!🚀

✨ 我的博客主页:喜欢吃燃面

📚 我的专栏(持续更新ing):
《C语言》 |
《C语言之数据结构》 |
《C++》 |
《Linux系统编程》

💖 超感谢你点开这篇博客!真心希望这些内容能帮到正在打怪升级的你~如果有任何想法、疑问,或者想交流学习心得,都欢迎留言/私信,咱们一起在编程路上互相陪伴、共同进步呀!

一. Socket地址与网络字节序转换

1. 网络地址结构体

在Linux网络编程中,sockaddr_in结构体是IPv4地址的核心表示方式。该结构体定义在<arpa/inet.h>头文件中,包含了地址族、端口号和IP地址三个关键字段。理解这个结构体是掌握网络编程的第一步。

c 复制代码
struct sockaddr_in {
    sa_family_t    sin_family;   // 地址族,AF_INET表示IPv4
    in_port_t      sin_port;     // 端口号,网络字节序
    struct in_addr sin_addr;     // IP地址
    char           sin_zero[8];  // 填充字节,保持与sockaddr大小一致
};

InetAddr类是对**sockaddr_in**的C++封装,它简化了地址的初始化过程。构造函数接收IP地址字符串和端口号,内部完成字符串到网络字节序的转换。这种封装方式在现代C++网络库中非常常见,它将底层C API的复杂性隐藏起来,提供更符合面向对象编程习惯的接口。

2. 字节序转换函数

网络协议要求数据以大端字节序 (Big-Endian)传输,而主机字节序可能是大端或小端(x86架构为小端)。因此,在发送数据前必须进行字节序转换。

Linux提供了四个核心转换函数,这些函数构成了网络编程的基础工具集:

函数 功能 方向
htons() Host to Network Short 主机→网络(16位)
htonl() Host to Network Long 主机→网络(32位)
ntohs() Network to Host Short 网络→主机(16位)
ntohl() Network to Host Long 网络→主机(32位)

inet_ntoa()inet_aton()是IP地址字符串与网络字节序之间的转换函数。inet_ntoa()将32位网络字节序IP地址转换为点分十进制字符串,而inet_aton()执行相反的操作。需要注意的是,inet_ntoa()返回的字符串存储在静态缓冲区中,因此不是线程安全的。在多线程环境中,应使用**inet_ntop() inet_pton()**这两个更现代的函数。

**inet_ntop() inet_pton()支持IPv4和IPv6双协议栈,是现代网络编程的首选。 inet_pton()将点分十进制字符串转换为网络字节序的二进制地址,而 inet_ntop()**将二进制地址转换回人类可读的字符串形式。这两个函数需要调用者提供目标缓冲区,避免了线程安全问题。
#mermaid-svg-ZWOtTstsnwjcNdBR{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-ZWOtTstsnwjcNdBR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZWOtTstsnwjcNdBR .error-icon{fill:#552222;}#mermaid-svg-ZWOtTstsnwjcNdBR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZWOtTstsnwjcNdBR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZWOtTstsnwjcNdBR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZWOtTstsnwjcNdBR .marker.cross{stroke:#333333;}#mermaid-svg-ZWOtTstsnwjcNdBR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZWOtTstsnwjcNdBR p{margin:0;}#mermaid-svg-ZWOtTstsnwjcNdBR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR .cluster-label text{fill:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR .cluster-label span{color:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR .cluster-label span p{background-color:transparent;}#mermaid-svg-ZWOtTstsnwjcNdBR .label text,#mermaid-svg-ZWOtTstsnwjcNdBR span{fill:#333;color:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR .node rect,#mermaid-svg-ZWOtTstsnwjcNdBR .node circle,#mermaid-svg-ZWOtTstsnwjcNdBR .node ellipse,#mermaid-svg-ZWOtTstsnwjcNdBR .node polygon,#mermaid-svg-ZWOtTstsnwjcNdBR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZWOtTstsnwjcNdBR .rough-node .label text,#mermaid-svg-ZWOtTstsnwjcNdBR .node .label text,#mermaid-svg-ZWOtTstsnwjcNdBR .image-shape .label,#mermaid-svg-ZWOtTstsnwjcNdBR .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZWOtTstsnwjcNdBR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZWOtTstsnwjcNdBR .rough-node .label,#mermaid-svg-ZWOtTstsnwjcNdBR .node .label,#mermaid-svg-ZWOtTstsnwjcNdBR .image-shape .label,#mermaid-svg-ZWOtTstsnwjcNdBR .icon-shape .label{text-align:center;}#mermaid-svg-ZWOtTstsnwjcNdBR .node.clickable{cursor:pointer;}#mermaid-svg-ZWOtTstsnwjcNdBR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZWOtTstsnwjcNdBR .arrowheadPath{fill:#333333;}#mermaid-svg-ZWOtTstsnwjcNdBR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZWOtTstsnwjcNdBR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZWOtTstsnwjcNdBR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZWOtTstsnwjcNdBR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZWOtTstsnwjcNdBR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZWOtTstsnwjcNdBR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZWOtTstsnwjcNdBR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZWOtTstsnwjcNdBR .cluster text{fill:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR .cluster span{color:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR 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-ZWOtTstsnwjcNdBR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZWOtTstsnwjcNdBR rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZWOtTstsnwjcNdBR .icon-shape,#mermaid-svg-ZWOtTstsnwjcNdBR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZWOtTstsnwjcNdBR .icon-shape p,#mermaid-svg-ZWOtTstsnwjcNdBR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZWOtTstsnwjcNdBR .icon-shape rect,#mermaid-svg-ZWOtTstsnwjcNdBR .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZWOtTstsnwjcNdBR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZWOtTstsnwjcNdBR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZWOtTstsnwjcNdBR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} inet_pton / inet_aton
inet_ntop / inet_ntoa
htons
ntohs
点分十进制字符串

192.168.1.1
网络字节序

32位整数
主机字节序

Port: 8080
网络字节序

Port: 0x901F

3. 文件描述符与Socket的关系

在Linux中,一切皆文件 。Socket本质上也是一种文件,通过文件描述符(File Descriptor)来操作。当调用socket()系统调用时,内核会创建一个struct socket结构体,并在进程的文件描述符表中分配一个条目。这个文件描述符就是后续所有Socket操作的句柄。
#mermaid-svg-F74dIO6jj1xH2bwD{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-F74dIO6jj1xH2bwD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-F74dIO6jj1xH2bwD .error-icon{fill:#552222;}#mermaid-svg-F74dIO6jj1xH2bwD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-F74dIO6jj1xH2bwD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-F74dIO6jj1xH2bwD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-F74dIO6jj1xH2bwD .marker.cross{stroke:#333333;}#mermaid-svg-F74dIO6jj1xH2bwD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-F74dIO6jj1xH2bwD p{margin:0;}#mermaid-svg-F74dIO6jj1xH2bwD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-F74dIO6jj1xH2bwD .cluster-label text{fill:#333;}#mermaid-svg-F74dIO6jj1xH2bwD .cluster-label span{color:#333;}#mermaid-svg-F74dIO6jj1xH2bwD .cluster-label span p{background-color:transparent;}#mermaid-svg-F74dIO6jj1xH2bwD .label text,#mermaid-svg-F74dIO6jj1xH2bwD span{fill:#333;color:#333;}#mermaid-svg-F74dIO6jj1xH2bwD .node rect,#mermaid-svg-F74dIO6jj1xH2bwD .node circle,#mermaid-svg-F74dIO6jj1xH2bwD .node ellipse,#mermaid-svg-F74dIO6jj1xH2bwD .node polygon,#mermaid-svg-F74dIO6jj1xH2bwD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-F74dIO6jj1xH2bwD .rough-node .label text,#mermaid-svg-F74dIO6jj1xH2bwD .node .label text,#mermaid-svg-F74dIO6jj1xH2bwD .image-shape .label,#mermaid-svg-F74dIO6jj1xH2bwD .icon-shape .label{text-anchor:middle;}#mermaid-svg-F74dIO6jj1xH2bwD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-F74dIO6jj1xH2bwD .rough-node .label,#mermaid-svg-F74dIO6jj1xH2bwD .node .label,#mermaid-svg-F74dIO6jj1xH2bwD .image-shape .label,#mermaid-svg-F74dIO6jj1xH2bwD .icon-shape .label{text-align:center;}#mermaid-svg-F74dIO6jj1xH2bwD .node.clickable{cursor:pointer;}#mermaid-svg-F74dIO6jj1xH2bwD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-F74dIO6jj1xH2bwD .arrowheadPath{fill:#333333;}#mermaid-svg-F74dIO6jj1xH2bwD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-F74dIO6jj1xH2bwD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-F74dIO6jj1xH2bwD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-F74dIO6jj1xH2bwD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-F74dIO6jj1xH2bwD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-F74dIO6jj1xH2bwD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-F74dIO6jj1xH2bwD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-F74dIO6jj1xH2bwD .cluster text{fill:#333;}#mermaid-svg-F74dIO6jj1xH2bwD .cluster span{color:#333;}#mermaid-svg-F74dIO6jj1xH2bwD 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-F74dIO6jj1xH2bwD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-F74dIO6jj1xH2bwD rect.text{fill:none;stroke-width:0;}#mermaid-svg-F74dIO6jj1xH2bwD .icon-shape,#mermaid-svg-F74dIO6jj1xH2bwD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-F74dIO6jj1xH2bwD .icon-shape p,#mermaid-svg-F74dIO6jj1xH2bwD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-F74dIO6jj1xH2bwD .icon-shape rect,#mermaid-svg-F74dIO6jj1xH2bwD .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-F74dIO6jj1xH2bwD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-F74dIO6jj1xH2bwD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-F74dIO6jj1xH2bwD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 进程文件描述符表

fd_array
struct file
struct socket
struct sock

sk_receive_queue

sk_write_queue
TCP协议栈
网卡驱动
物理网络

struct socket是BSD Socket层的抽象,而struct sock是具体的协议实现(如TCP、UDP)。sk_receive_queuesk_write_queue分别是接收队列和发送队列,它们在内核空间中缓存数据,实现了用户态与内核态之间的数据交换。


二. TCP Socket通信模型与数据流

1. TCP协议栈分层结构

TCP Socket通信遵循OSI七层模型,但在实际实现中通常采用TCP/IP四层模型。数据在发送时从上到下逐层封装,在接收时从下到上逐层解封装。
#mermaid-svg-zEG164mF75R93t4A{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-zEG164mF75R93t4A .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zEG164mF75R93t4A .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zEG164mF75R93t4A .error-icon{fill:#552222;}#mermaid-svg-zEG164mF75R93t4A .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zEG164mF75R93t4A .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zEG164mF75R93t4A .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zEG164mF75R93t4A .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zEG164mF75R93t4A .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zEG164mF75R93t4A .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zEG164mF75R93t4A .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zEG164mF75R93t4A .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zEG164mF75R93t4A .marker.cross{stroke:#333333;}#mermaid-svg-zEG164mF75R93t4A svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zEG164mF75R93t4A p{margin:0;}#mermaid-svg-zEG164mF75R93t4A .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zEG164mF75R93t4A .cluster-label text{fill:#333;}#mermaid-svg-zEG164mF75R93t4A .cluster-label span{color:#333;}#mermaid-svg-zEG164mF75R93t4A .cluster-label span p{background-color:transparent;}#mermaid-svg-zEG164mF75R93t4A .label text,#mermaid-svg-zEG164mF75R93t4A span{fill:#333;color:#333;}#mermaid-svg-zEG164mF75R93t4A .node rect,#mermaid-svg-zEG164mF75R93t4A .node circle,#mermaid-svg-zEG164mF75R93t4A .node ellipse,#mermaid-svg-zEG164mF75R93t4A .node polygon,#mermaid-svg-zEG164mF75R93t4A .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zEG164mF75R93t4A .rough-node .label text,#mermaid-svg-zEG164mF75R93t4A .node .label text,#mermaid-svg-zEG164mF75R93t4A .image-shape .label,#mermaid-svg-zEG164mF75R93t4A .icon-shape .label{text-anchor:middle;}#mermaid-svg-zEG164mF75R93t4A .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zEG164mF75R93t4A .rough-node .label,#mermaid-svg-zEG164mF75R93t4A .node .label,#mermaid-svg-zEG164mF75R93t4A .image-shape .label,#mermaid-svg-zEG164mF75R93t4A .icon-shape .label{text-align:center;}#mermaid-svg-zEG164mF75R93t4A .node.clickable{cursor:pointer;}#mermaid-svg-zEG164mF75R93t4A .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zEG164mF75R93t4A .arrowheadPath{fill:#333333;}#mermaid-svg-zEG164mF75R93t4A .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zEG164mF75R93t4A .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zEG164mF75R93t4A .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zEG164mF75R93t4A .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zEG164mF75R93t4A .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zEG164mF75R93t4A .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zEG164mF75R93t4A .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zEG164mF75R93t4A .cluster text{fill:#333;}#mermaid-svg-zEG164mF75R93t4A .cluster span{color:#333;}#mermaid-svg-zEG164mF75R93t4A 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-zEG164mF75R93t4A .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zEG164mF75R93t4A rect.text{fill:none;stroke-width:0;}#mermaid-svg-zEG164mF75R93t4A .icon-shape,#mermaid-svg-zEG164mF75R93t4A .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zEG164mF75R93t4A .icon-shape p,#mermaid-svg-zEG164mF75R93t4A .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zEG164mF75R93t4A .icon-shape rect,#mermaid-svg-zEG164mF75R93t4A .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zEG164mF75R93t4A .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zEG164mF75R93t4A .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zEG164mF75R93t4A :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接收端
发送端
物理网络
应用层

用户数据
传输层

TCP头+数据
网络层

IP头+TCP头+数据
链路层

以太网头+IP头+TCP头+数据
链路层
网络层
传输层
应用层

2. Socket缓冲区机制

TCP Socket是全双工 的,通信双方都拥有独立的发送缓冲区接收缓冲区。这种设计是理解网络编程中阻塞行为的关键。

当应用程序调用write()或**send()**时,数据首先被拷贝到内核的发送缓冲区。如果发送缓冲区已满,write()调用会阻塞(在非阻塞模式下返回EAGAIN错误)。内核的TCP协议栈负责将发送缓冲区中的数据分段、添加TCP头部、计算校验和,然后交给IP层发送。

当数据到达网卡时,网卡通过DMA将数据放入内存,触发中断。内核的中断处理程序将数据交给TCP协议栈,TCP层去除头部后将数据放入接收缓冲区。应用程序调用read()或**recv()**时,从接收缓冲区拷贝数据到用户空间。如果接收缓冲区为空,read()调用会阻塞。
#mermaid-svg-kGTcfPgwNdI2ogP0{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-kGTcfPgwNdI2ogP0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kGTcfPgwNdI2ogP0 .error-icon{fill:#552222;}#mermaid-svg-kGTcfPgwNdI2ogP0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kGTcfPgwNdI2ogP0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .marker.cross{stroke:#333333;}#mermaid-svg-kGTcfPgwNdI2ogP0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kGTcfPgwNdI2ogP0 p{margin:0;}#mermaid-svg-kGTcfPgwNdI2ogP0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .cluster-label text{fill:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .cluster-label span{color:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .cluster-label span p{background-color:transparent;}#mermaid-svg-kGTcfPgwNdI2ogP0 .label text,#mermaid-svg-kGTcfPgwNdI2ogP0 span{fill:#333;color:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .node rect,#mermaid-svg-kGTcfPgwNdI2ogP0 .node circle,#mermaid-svg-kGTcfPgwNdI2ogP0 .node ellipse,#mermaid-svg-kGTcfPgwNdI2ogP0 .node polygon,#mermaid-svg-kGTcfPgwNdI2ogP0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .rough-node .label text,#mermaid-svg-kGTcfPgwNdI2ogP0 .node .label text,#mermaid-svg-kGTcfPgwNdI2ogP0 .image-shape .label,#mermaid-svg-kGTcfPgwNdI2ogP0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-kGTcfPgwNdI2ogP0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .rough-node .label,#mermaid-svg-kGTcfPgwNdI2ogP0 .node .label,#mermaid-svg-kGTcfPgwNdI2ogP0 .image-shape .label,#mermaid-svg-kGTcfPgwNdI2ogP0 .icon-shape .label{text-align:center;}#mermaid-svg-kGTcfPgwNdI2ogP0 .node.clickable{cursor:pointer;}#mermaid-svg-kGTcfPgwNdI2ogP0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .arrowheadPath{fill:#333333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kGTcfPgwNdI2ogP0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kGTcfPgwNdI2ogP0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kGTcfPgwNdI2ogP0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kGTcfPgwNdI2ogP0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .cluster text{fill:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 .cluster span{color:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 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-kGTcfPgwNdI2ogP0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kGTcfPgwNdI2ogP0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-kGTcfPgwNdI2ogP0 .icon-shape,#mermaid-svg-kGTcfPgwNdI2ogP0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kGTcfPgwNdI2ogP0 .icon-shape p,#mermaid-svg-kGTcfPgwNdI2ogP0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kGTcfPgwNdI2ogP0 .icon-shape rect,#mermaid-svg-kGTcfPgwNdI2ogP0 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kGTcfPgwNdI2ogP0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kGTcfPgwNdI2ogP0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kGTcfPgwNdI2ogP0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 主机B
主机A
write()

拷贝数据
read()

拷贝数据
write()
read()
TCP协议栈

分段/封装
TCP协议栈

重组/解封装
TCP协议栈
用户空间
内核发送缓冲区
内核接收缓冲区
用户空间
内核发送缓冲区
内核接收缓冲区
物理网络

3. 生产者-消费者模型

Socket缓冲区本质上是一个生产者-消费者模型的实例。发送方是生产者,向发送缓冲区生产数据;TCP协议栈是消费者,从发送缓冲区消费数据并发送。在接收端,网络是生产者,向接收缓冲区生产数据;应用程序是消费者,从接收缓冲区读取数据。

这种模型解释了为什么write()read()会阻塞:当缓冲区满时,生产者需要等待消费者消费数据;当缓冲区空时,消费者需要等待生产者生产数据。理解这一点对于编写高效的网络程序至关重要。

操作系统内部可能会收到多个报文,还没来得及放入到接收缓冲区。这时,操作系统需要对这些报文进行管理,维护一个报文队列,按序重组后交付给接收缓冲区。这就是TCP的按序交付保证。


三. Socket文件描述符与连接管理

1. listen()系统调用

listen()函数将主动Socket转换为被动Socket,使其能够接受传入的连接请求。这是服务器端编程的关键步骤。

c 复制代码
#include <sys/socket.h>
int listen(int sockfd, int backlog);
  • sockfd:由socket()创建的Socket文件描述符
  • backlog:连接队列的最大长度,即**半连接队列(SYN队列)全连接队列(accept队列)**的总长度

backlog参数决定了内核能够同时维护的待处理连接数。如果连接请求到达时队列已满,客户端可能会收到ECONNREFUSED错误,或者连接被静默丢弃(取决于TCP实现)。在生产环境中,需要根据服务器的处理能力和并发需求合理设置这个值。

2. accept()系统调用

accept()函数从全连接队列中取出一个已完成的连接,并创建一个新的Socket文件描述符来代表这个连接。

c 复制代码
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

关键理解accept()返回的是一个新的文件描述符,这个描述符代表与特定客户端的连接。而传入的sockfd监听Socket(Listen Socket),它继续监听新的连接请求。这意味着一个服务器进程可以同时管理一个监听Socket和多个连接Socket。
#mermaid-svg-bPOaMW1f51F1Q3Pn{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-bPOaMW1f51F1Q3Pn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bPOaMW1f51F1Q3Pn .error-icon{fill:#552222;}#mermaid-svg-bPOaMW1f51F1Q3Pn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bPOaMW1f51F1Q3Pn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .marker.cross{stroke:#333333;}#mermaid-svg-bPOaMW1f51F1Q3Pn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bPOaMW1f51F1Q3Pn p{margin:0;}#mermaid-svg-bPOaMW1f51F1Q3Pn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .cluster-label text{fill:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .cluster-label span{color:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .cluster-label span p{background-color:transparent;}#mermaid-svg-bPOaMW1f51F1Q3Pn .label text,#mermaid-svg-bPOaMW1f51F1Q3Pn span{fill:#333;color:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .node rect,#mermaid-svg-bPOaMW1f51F1Q3Pn .node circle,#mermaid-svg-bPOaMW1f51F1Q3Pn .node ellipse,#mermaid-svg-bPOaMW1f51F1Q3Pn .node polygon,#mermaid-svg-bPOaMW1f51F1Q3Pn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .rough-node .label text,#mermaid-svg-bPOaMW1f51F1Q3Pn .node .label text,#mermaid-svg-bPOaMW1f51F1Q3Pn .image-shape .label,#mermaid-svg-bPOaMW1f51F1Q3Pn .icon-shape .label{text-anchor:middle;}#mermaid-svg-bPOaMW1f51F1Q3Pn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .rough-node .label,#mermaid-svg-bPOaMW1f51F1Q3Pn .node .label,#mermaid-svg-bPOaMW1f51F1Q3Pn .image-shape .label,#mermaid-svg-bPOaMW1f51F1Q3Pn .icon-shape .label{text-align:center;}#mermaid-svg-bPOaMW1f51F1Q3Pn .node.clickable{cursor:pointer;}#mermaid-svg-bPOaMW1f51F1Q3Pn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .arrowheadPath{fill:#333333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bPOaMW1f51F1Q3Pn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bPOaMW1f51F1Q3Pn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bPOaMW1f51F1Q3Pn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bPOaMW1f51F1Q3Pn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .cluster text{fill:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn .cluster span{color:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn 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-bPOaMW1f51F1Q3Pn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bPOaMW1f51F1Q3Pn rect.text{fill:none;stroke-width:0;}#mermaid-svg-bPOaMW1f51F1Q3Pn .icon-shape,#mermaid-svg-bPOaMW1f51F1Q3Pn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bPOaMW1f51F1Q3Pn .icon-shape p,#mermaid-svg-bPOaMW1f51F1Q3Pn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bPOaMW1f51F1Q3Pn .icon-shape rect,#mermaid-svg-bPOaMW1f51F1Q3Pn .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bPOaMW1f51F1Q3Pn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bPOaMW1f51F1Q3Pn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bPOaMW1f51F1Q3Pn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} accept()
accept()
accept()
accept()
继续监听...
监听Socket

Listen Socket
IO Socket 1

连接: 张三
IO Socket 2

连接: 李四
IO Socket 3

连接: 王五
IO Socket 4

连接: 赵六
新连接请求

accept()的第二个参数addr用于获取客户端的IP地址和端口号信息。如果不需要这些信息,可以传入NULL。成功时返回一个非负整数(新的文件描述符),失败时返回-1并设置errno

3. 连接与Socket的关系

一个Socket代表一条连接 。这是理解并发服务器设计的基础。当服务器需要同时处理多个客户端时,通常为每个连接创建独立的线程或进程,或者使用I/O多路复用(如select()poll()epoll())在单个线程中管理多个Socket。
#mermaid-svg-ry6ThuPmKHAddqsT{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-ry6ThuPmKHAddqsT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ry6ThuPmKHAddqsT .error-icon{fill:#552222;}#mermaid-svg-ry6ThuPmKHAddqsT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ry6ThuPmKHAddqsT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ry6ThuPmKHAddqsT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ry6ThuPmKHAddqsT .marker.cross{stroke:#333333;}#mermaid-svg-ry6ThuPmKHAddqsT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ry6ThuPmKHAddqsT p{margin:0;}#mermaid-svg-ry6ThuPmKHAddqsT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ry6ThuPmKHAddqsT .cluster-label text{fill:#333;}#mermaid-svg-ry6ThuPmKHAddqsT .cluster-label span{color:#333;}#mermaid-svg-ry6ThuPmKHAddqsT .cluster-label span p{background-color:transparent;}#mermaid-svg-ry6ThuPmKHAddqsT .label text,#mermaid-svg-ry6ThuPmKHAddqsT span{fill:#333;color:#333;}#mermaid-svg-ry6ThuPmKHAddqsT .node rect,#mermaid-svg-ry6ThuPmKHAddqsT .node circle,#mermaid-svg-ry6ThuPmKHAddqsT .node ellipse,#mermaid-svg-ry6ThuPmKHAddqsT .node polygon,#mermaid-svg-ry6ThuPmKHAddqsT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ry6ThuPmKHAddqsT .rough-node .label text,#mermaid-svg-ry6ThuPmKHAddqsT .node .label text,#mermaid-svg-ry6ThuPmKHAddqsT .image-shape .label,#mermaid-svg-ry6ThuPmKHAddqsT .icon-shape .label{text-anchor:middle;}#mermaid-svg-ry6ThuPmKHAddqsT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ry6ThuPmKHAddqsT .rough-node .label,#mermaid-svg-ry6ThuPmKHAddqsT .node .label,#mermaid-svg-ry6ThuPmKHAddqsT .image-shape .label,#mermaid-svg-ry6ThuPmKHAddqsT .icon-shape .label{text-align:center;}#mermaid-svg-ry6ThuPmKHAddqsT .node.clickable{cursor:pointer;}#mermaid-svg-ry6ThuPmKHAddqsT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ry6ThuPmKHAddqsT .arrowheadPath{fill:#333333;}#mermaid-svg-ry6ThuPmKHAddqsT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ry6ThuPmKHAddqsT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ry6ThuPmKHAddqsT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ry6ThuPmKHAddqsT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ry6ThuPmKHAddqsT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ry6ThuPmKHAddqsT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ry6ThuPmKHAddqsT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ry6ThuPmKHAddqsT .cluster text{fill:#333;}#mermaid-svg-ry6ThuPmKHAddqsT .cluster span{color:#333;}#mermaid-svg-ry6ThuPmKHAddqsT 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-ry6ThuPmKHAddqsT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ry6ThuPmKHAddqsT rect.text{fill:none;stroke-width:0;}#mermaid-svg-ry6ThuPmKHAddqsT .icon-shape,#mermaid-svg-ry6ThuPmKHAddqsT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ry6ThuPmKHAddqsT .icon-shape p,#mermaid-svg-ry6ThuPmKHAddqsT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ry6ThuPmKHAddqsT .icon-shape rect,#mermaid-svg-ry6ThuPmKHAddqsT .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ry6ThuPmKHAddqsT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ry6ThuPmKHAddqsT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ry6ThuPmKHAddqsT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
服务器进程
accept()
accept()
accept()
connect()
connect()
connect()
监听Socket

Port: 8080
连接Socket 1
连接Socket 2
连接Socket 3
客户端A
客户端B
客户端C


四. recv/send与自定义协议设计

1. recv()和send()系统调用

**recv() send()**是TCP Socket数据收发的核心函数。

c 复制代码
#include <sys/socket.h>
ssize_t recv(int sockfd, void buf[.len], size_t len, int flags);
ssize_t send(int sockfd, const void buf[.len], size_t len, int flags);

**recv()从连接Socket的接收缓冲区读取数据, send()**向连接Socket的发送缓冲区写入数据。flags参数可以指定特殊行为,如MSG_PEEK(窥视数据但不移除)和MSG_DONTWAIT(非阻塞操作)。

2. TCP流式传输的本质问题

TCP是面向字节流 的协议,不保留消息边界。这意味着发送方分两次发送的数据,接收方可能一次性收到;或者发送方一次发送的数据,接收方需要多次读取才能收完。这就是粘包问题

例如,发送方发送"Hello"和"World"两个消息,接收方可能收到"HelloWorld"(粘包),或者只收到"Hel"(半包)。应用程序必须自己处理消息的边界识别。

3. 自定义应用层协议

为了解决粘包问题,需要定义应用层协议。协议规定了消息的格式,使接收方能够正确解析出完整的消息。

常见的协议设计模式包括:

模式一:固定长度消息

每条消息长度固定,接收方每次读取固定字节数。简单但不够灵活。

模式二:特殊分隔符

使用特殊字符(如\n\r\n)作为消息结束标志。适合文本协议,但消息内容不能包含分隔符。

模式三:长度前缀(推荐)

在消息头部添加一个固定长度的字段,表示消息体的长度。接收方先读取长度,再根据长度读取完整消息。
#mermaid-svg-6S6oDW4S9xdKeWaX{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-6S6oDW4S9xdKeWaX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6S6oDW4S9xdKeWaX .error-icon{fill:#552222;}#mermaid-svg-6S6oDW4S9xdKeWaX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6S6oDW4S9xdKeWaX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6S6oDW4S9xdKeWaX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6S6oDW4S9xdKeWaX .marker.cross{stroke:#333333;}#mermaid-svg-6S6oDW4S9xdKeWaX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6S6oDW4S9xdKeWaX p{margin:0;}#mermaid-svg-6S6oDW4S9xdKeWaX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX .cluster-label text{fill:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX .cluster-label span{color:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX .cluster-label span p{background-color:transparent;}#mermaid-svg-6S6oDW4S9xdKeWaX .label text,#mermaid-svg-6S6oDW4S9xdKeWaX span{fill:#333;color:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX .node rect,#mermaid-svg-6S6oDW4S9xdKeWaX .node circle,#mermaid-svg-6S6oDW4S9xdKeWaX .node ellipse,#mermaid-svg-6S6oDW4S9xdKeWaX .node polygon,#mermaid-svg-6S6oDW4S9xdKeWaX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6S6oDW4S9xdKeWaX .rough-node .label text,#mermaid-svg-6S6oDW4S9xdKeWaX .node .label text,#mermaid-svg-6S6oDW4S9xdKeWaX .image-shape .label,#mermaid-svg-6S6oDW4S9xdKeWaX .icon-shape .label{text-anchor:middle;}#mermaid-svg-6S6oDW4S9xdKeWaX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6S6oDW4S9xdKeWaX .rough-node .label,#mermaid-svg-6S6oDW4S9xdKeWaX .node .label,#mermaid-svg-6S6oDW4S9xdKeWaX .image-shape .label,#mermaid-svg-6S6oDW4S9xdKeWaX .icon-shape .label{text-align:center;}#mermaid-svg-6S6oDW4S9xdKeWaX .node.clickable{cursor:pointer;}#mermaid-svg-6S6oDW4S9xdKeWaX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6S6oDW4S9xdKeWaX .arrowheadPath{fill:#333333;}#mermaid-svg-6S6oDW4S9xdKeWaX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6S6oDW4S9xdKeWaX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6S6oDW4S9xdKeWaX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6S6oDW4S9xdKeWaX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6S6oDW4S9xdKeWaX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6S6oDW4S9xdKeWaX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6S6oDW4S9xdKeWaX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6S6oDW4S9xdKeWaX .cluster text{fill:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX .cluster span{color:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX 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-6S6oDW4S9xdKeWaX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6S6oDW4S9xdKeWaX rect.text{fill:none;stroke-width:0;}#mermaid-svg-6S6oDW4S9xdKeWaX .icon-shape,#mermaid-svg-6S6oDW4S9xdKeWaX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6S6oDW4S9xdKeWaX .icon-shape p,#mermaid-svg-6S6oDW4S9xdKeWaX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6S6oDW4S9xdKeWaX .icon-shape rect,#mermaid-svg-6S6oDW4S9xdKeWaX .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6S6oDW4S9xdKeWaX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6S6oDW4S9xdKeWaX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6S6oDW4S9xdKeWaX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 协议格式
有效载荷长度

4字节
有效载荷内容

变长
\r\n

分隔符
有效载荷长度
有效载荷内容
\r\n

这种"长度+内容+分隔符"的格式兼具效率和可读性。长度字段用于快速定位消息边界,分隔符用于调试时肉眼识别消息边界。

4. Request/Response消息结构

在客户端-服务器架构中,通常定义请求(Request)和响应(Response)两种消息类型。

cpp 复制代码
class Request {
public:
    Request();
    ~Request();
private:
    int _data_x;      // 操作数1
    int _data_y;      // 操作数2
    char _oper;       // 操作符: +, -, *, /, %
};

class Response {
public:
    Response();
    ~Response();
private:
    int _result;      // 计算结果
    int _code;        // 状态码
};

Request封装了客户端的请求信息(如计算器的操作数和操作符),Response封装了服务器的处理结果。这种设计将业务逻辑与网络传输解耦,提高了代码的可维护性。

5. 序列化与反序列化

序列化 是将内存中的对象转换为字节流的过程,反序列化是相反的过程。这是网络通信中不可或缺的一环。
#mermaid-svg-k0ATDFCTwLRIpvsp{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-k0ATDFCTwLRIpvsp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-k0ATDFCTwLRIpvsp .error-icon{fill:#552222;}#mermaid-svg-k0ATDFCTwLRIpvsp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-k0ATDFCTwLRIpvsp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-k0ATDFCTwLRIpvsp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-k0ATDFCTwLRIpvsp .marker.cross{stroke:#333333;}#mermaid-svg-k0ATDFCTwLRIpvsp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-k0ATDFCTwLRIpvsp p{margin:0;}#mermaid-svg-k0ATDFCTwLRIpvsp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp .cluster-label text{fill:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp .cluster-label span{color:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp .cluster-label span p{background-color:transparent;}#mermaid-svg-k0ATDFCTwLRIpvsp .label text,#mermaid-svg-k0ATDFCTwLRIpvsp span{fill:#333;color:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp .node rect,#mermaid-svg-k0ATDFCTwLRIpvsp .node circle,#mermaid-svg-k0ATDFCTwLRIpvsp .node ellipse,#mermaid-svg-k0ATDFCTwLRIpvsp .node polygon,#mermaid-svg-k0ATDFCTwLRIpvsp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-k0ATDFCTwLRIpvsp .rough-node .label text,#mermaid-svg-k0ATDFCTwLRIpvsp .node .label text,#mermaid-svg-k0ATDFCTwLRIpvsp .image-shape .label,#mermaid-svg-k0ATDFCTwLRIpvsp .icon-shape .label{text-anchor:middle;}#mermaid-svg-k0ATDFCTwLRIpvsp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-k0ATDFCTwLRIpvsp .rough-node .label,#mermaid-svg-k0ATDFCTwLRIpvsp .node .label,#mermaid-svg-k0ATDFCTwLRIpvsp .image-shape .label,#mermaid-svg-k0ATDFCTwLRIpvsp .icon-shape .label{text-align:center;}#mermaid-svg-k0ATDFCTwLRIpvsp .node.clickable{cursor:pointer;}#mermaid-svg-k0ATDFCTwLRIpvsp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-k0ATDFCTwLRIpvsp .arrowheadPath{fill:#333333;}#mermaid-svg-k0ATDFCTwLRIpvsp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-k0ATDFCTwLRIpvsp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-k0ATDFCTwLRIpvsp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k0ATDFCTwLRIpvsp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-k0ATDFCTwLRIpvsp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k0ATDFCTwLRIpvsp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-k0ATDFCTwLRIpvsp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-k0ATDFCTwLRIpvsp .cluster text{fill:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp .cluster span{color:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp 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-k0ATDFCTwLRIpvsp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-k0ATDFCTwLRIpvsp rect.text{fill:none;stroke-width:0;}#mermaid-svg-k0ATDFCTwLRIpvsp .icon-shape,#mermaid-svg-k0ATDFCTwLRIpvsp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k0ATDFCTwLRIpvsp .icon-shape p,#mermaid-svg-k0ATDFCTwLRIpvsp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-k0ATDFCTwLRIpvsp .icon-shape rect,#mermaid-svg-k0ATDFCTwLRIpvsp .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k0ATDFCTwLRIpvsp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-k0ATDFCTwLRIpvsp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-k0ATDFCTwLRIpvsp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接收端
发送端
序列化
网络传输
反序列化
struct/class

Request对象
字节流

10 20 +
字节流
struct/class

Request对象

序列化具有以下扩展性优势

  1. 跨平台:不同操作系统、不同编程语言之间可以交换数据
  2. 持久化:字节流可以写入文件或数据库
  3. 版本兼容:可以在协议中添加新字段而不破坏旧版本兼容性

在网络通信中,发送方将Request对象序列化为字节流,通过Socket发送;接收方收到字节流后,反序列化为Request对象,执行业务逻辑,然后将Response对象序列化后发送回客户端。
#mermaid-svg-4FC8zzvkx1i0dEQ3{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-4FC8zzvkx1i0dEQ3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .error-icon{fill:#552222;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .marker.cross{stroke:#333333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 p{margin:0;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .cluster-label text{fill:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .cluster-label span{color:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .cluster-label span p{background-color:transparent;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .label text,#mermaid-svg-4FC8zzvkx1i0dEQ3 span{fill:#333;color:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .node rect,#mermaid-svg-4FC8zzvkx1i0dEQ3 .node circle,#mermaid-svg-4FC8zzvkx1i0dEQ3 .node ellipse,#mermaid-svg-4FC8zzvkx1i0dEQ3 .node polygon,#mermaid-svg-4FC8zzvkx1i0dEQ3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .rough-node .label text,#mermaid-svg-4FC8zzvkx1i0dEQ3 .node .label text,#mermaid-svg-4FC8zzvkx1i0dEQ3 .image-shape .label,#mermaid-svg-4FC8zzvkx1i0dEQ3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .rough-node .label,#mermaid-svg-4FC8zzvkx1i0dEQ3 .node .label,#mermaid-svg-4FC8zzvkx1i0dEQ3 .image-shape .label,#mermaid-svg-4FC8zzvkx1i0dEQ3 .icon-shape .label{text-align:center;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .node.clickable{cursor:pointer;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .arrowheadPath{fill:#333333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4FC8zzvkx1i0dEQ3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4FC8zzvkx1i0dEQ3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4FC8zzvkx1i0dEQ3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .cluster text{fill:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .cluster span{color:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 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-4FC8zzvkx1i0dEQ3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4FC8zzvkx1i0dEQ3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .icon-shape,#mermaid-svg-4FC8zzvkx1i0dEQ3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .icon-shape p,#mermaid-svg-4FC8zzvkx1i0dEQ3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .icon-shape rect,#mermaid-svg-4FC8zzvkx1i0dEQ3 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4FC8zzvkx1i0dEQ3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4FC8zzvkx1i0dEQ3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4FC8zzvkx1i0dEQ3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 主机B
网络
主机A
序列化
write()
read()
反序列化
TCP/IP
TCP/IP
read()
反序列化
业务处理
序列化
write()
TCP/IP
应用层

Request对象
字节流
内核发送缓冲区
内核接收缓冲区
字节流
应用层

Response对象
内核接收缓冲区
字节流
应用层

Request对象
应用层

Response对象
字节流
内核发送缓冲区


五. 分层架构与解耦设计

1. 三层架构设计

良好的网络程序应该采用分层架构,将不同职责分离。典型的三层架构包括:

第一层:网络层(TcpServer)

负责Socket的创建、绑定、监听、接受连接、数据收发。这一层只关心字节流的传输,不关心业务逻辑。

第二层:协议层(Protocol)

负责消息的序列化、反序列化、协议解析。这一层定义了通信双方的数据格式约定。

第三层:业务层(Calculator/Handler)

负责具体的业务逻辑处理。这一层只操作高层对象(如Request/Response),不关心网络细节。
#mermaid-svg-mxPuSEINdXP151Gg{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-mxPuSEINdXP151Gg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mxPuSEINdXP151Gg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mxPuSEINdXP151Gg .error-icon{fill:#552222;}#mermaid-svg-mxPuSEINdXP151Gg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mxPuSEINdXP151Gg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mxPuSEINdXP151Gg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mxPuSEINdXP151Gg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mxPuSEINdXP151Gg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mxPuSEINdXP151Gg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mxPuSEINdXP151Gg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mxPuSEINdXP151Gg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mxPuSEINdXP151Gg .marker.cross{stroke:#333333;}#mermaid-svg-mxPuSEINdXP151Gg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mxPuSEINdXP151Gg p{margin:0;}#mermaid-svg-mxPuSEINdXP151Gg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mxPuSEINdXP151Gg .cluster-label text{fill:#333;}#mermaid-svg-mxPuSEINdXP151Gg .cluster-label span{color:#333;}#mermaid-svg-mxPuSEINdXP151Gg .cluster-label span p{background-color:transparent;}#mermaid-svg-mxPuSEINdXP151Gg .label text,#mermaid-svg-mxPuSEINdXP151Gg span{fill:#333;color:#333;}#mermaid-svg-mxPuSEINdXP151Gg .node rect,#mermaid-svg-mxPuSEINdXP151Gg .node circle,#mermaid-svg-mxPuSEINdXP151Gg .node ellipse,#mermaid-svg-mxPuSEINdXP151Gg .node polygon,#mermaid-svg-mxPuSEINdXP151Gg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mxPuSEINdXP151Gg .rough-node .label text,#mermaid-svg-mxPuSEINdXP151Gg .node .label text,#mermaid-svg-mxPuSEINdXP151Gg .image-shape .label,#mermaid-svg-mxPuSEINdXP151Gg .icon-shape .label{text-anchor:middle;}#mermaid-svg-mxPuSEINdXP151Gg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mxPuSEINdXP151Gg .rough-node .label,#mermaid-svg-mxPuSEINdXP151Gg .node .label,#mermaid-svg-mxPuSEINdXP151Gg .image-shape .label,#mermaid-svg-mxPuSEINdXP151Gg .icon-shape .label{text-align:center;}#mermaid-svg-mxPuSEINdXP151Gg .node.clickable{cursor:pointer;}#mermaid-svg-mxPuSEINdXP151Gg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mxPuSEINdXP151Gg .arrowheadPath{fill:#333333;}#mermaid-svg-mxPuSEINdXP151Gg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mxPuSEINdXP151Gg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mxPuSEINdXP151Gg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mxPuSEINdXP151Gg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mxPuSEINdXP151Gg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mxPuSEINdXP151Gg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mxPuSEINdXP151Gg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mxPuSEINdXP151Gg .cluster text{fill:#333;}#mermaid-svg-mxPuSEINdXP151Gg .cluster span{color:#333;}#mermaid-svg-mxPuSEINdXP151Gg 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-mxPuSEINdXP151Gg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mxPuSEINdXP151Gg rect.text{fill:none;stroke-width:0;}#mermaid-svg-mxPuSEINdXP151Gg .icon-shape,#mermaid-svg-mxPuSEINdXP151Gg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mxPuSEINdXP151Gg .icon-shape p,#mermaid-svg-mxPuSEINdXP151Gg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mxPuSEINdXP151Gg .icon-shape rect,#mermaid-svg-mxPuSEINdXP151Gg .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mxPuSEINdXP151Gg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mxPuSEINdXP151Gg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mxPuSEINdXP151Gg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 三层架构
Request/Response

对象
字节流

string
Socket API
业务层

Calculator
协议层

Protocol
网络层

TcpServer
操作系统

TCP/IP协议栈

2. 回调机制与依赖注入

三层之间通过回调函数(Callback)进行交互,实现了依赖反转

cpp 复制代码
int main() {
    // 1. 定义计算机
    std::unique_ptr<Calculator> cal = std::make_unique<Calculator>();
    
    // 2. 定义协议对象
    std::unique_ptr<Protocol> protocol = std::make_unique<Protocol>(
        [&cal](Request &req) -> Response {
            return cal->Execute(req);
        }
    );
    
    // 3. 定义网络对象
    std::unique_ptr<TcpServer> tsr = std::make_unique<TcpServer>(
        [&protocol](std::string &inbuffer) -> std::string {
            return protocol->Parse(inbuffer);
        }
    );
    
    return 0;
}

这种设计体现了单一职责原则 :每个类只负责一个层面的功能,通过回调将各层连接起来。TcpServer收到数据后调用Protocol的解析回调,Protocol解析出Request后调用Calculator的业务处理回调,Calculator返回Response后,Protocol将其序列化,TcpServer最终发送出去。

3. OSI模型与协议分层

OSI七层模型是网络协议设计的理论基础,每一层都有明确的职责:

层级 名称 职责 典型协议
7 应用层 针对特定应用的协议 HTTP, FTP, SMTP
6 表示层 设备固有数据格式和网络标准数据格式的转换 SSL/TLS, ASCII
5 会话层 通信管理,负责建立和断开连接 NetBIOS, RPC
4 传输层 管理两个节点之间的数据传输,负责可靠传输 TCP, UDP
3 网络层 地址管理与路由选择 IP, ICMP, ARP
2 数据链路层 互连设备之间传送和识别数据帧 Ethernet, PPP
1 物理层 以0、1比特流的形式传输数据 光纤、双绞线

#mermaid-svg-eBJ9VbFTBlcPc1LW{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-eBJ9VbFTBlcPc1LW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eBJ9VbFTBlcPc1LW .error-icon{fill:#552222;}#mermaid-svg-eBJ9VbFTBlcPc1LW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eBJ9VbFTBlcPc1LW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .marker.cross{stroke:#333333;}#mermaid-svg-eBJ9VbFTBlcPc1LW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eBJ9VbFTBlcPc1LW p{margin:0;}#mermaid-svg-eBJ9VbFTBlcPc1LW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .cluster-label text{fill:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .cluster-label span{color:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .cluster-label span p{background-color:transparent;}#mermaid-svg-eBJ9VbFTBlcPc1LW .label text,#mermaid-svg-eBJ9VbFTBlcPc1LW span{fill:#333;color:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .node rect,#mermaid-svg-eBJ9VbFTBlcPc1LW .node circle,#mermaid-svg-eBJ9VbFTBlcPc1LW .node ellipse,#mermaid-svg-eBJ9VbFTBlcPc1LW .node polygon,#mermaid-svg-eBJ9VbFTBlcPc1LW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .rough-node .label text,#mermaid-svg-eBJ9VbFTBlcPc1LW .node .label text,#mermaid-svg-eBJ9VbFTBlcPc1LW .image-shape .label,#mermaid-svg-eBJ9VbFTBlcPc1LW .icon-shape .label{text-anchor:middle;}#mermaid-svg-eBJ9VbFTBlcPc1LW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .rough-node .label,#mermaid-svg-eBJ9VbFTBlcPc1LW .node .label,#mermaid-svg-eBJ9VbFTBlcPc1LW .image-shape .label,#mermaid-svg-eBJ9VbFTBlcPc1LW .icon-shape .label{text-align:center;}#mermaid-svg-eBJ9VbFTBlcPc1LW .node.clickable{cursor:pointer;}#mermaid-svg-eBJ9VbFTBlcPc1LW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .arrowheadPath{fill:#333333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eBJ9VbFTBlcPc1LW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eBJ9VbFTBlcPc1LW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eBJ9VbFTBlcPc1LW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eBJ9VbFTBlcPc1LW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .cluster text{fill:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW .cluster span{color:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW 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-eBJ9VbFTBlcPc1LW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eBJ9VbFTBlcPc1LW rect.text{fill:none;stroke-width:0;}#mermaid-svg-eBJ9VbFTBlcPc1LW .icon-shape,#mermaid-svg-eBJ9VbFTBlcPc1LW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eBJ9VbFTBlcPc1LW .icon-shape p,#mermaid-svg-eBJ9VbFTBlcPc1LW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eBJ9VbFTBlcPc1LW .icon-shape rect,#mermaid-svg-eBJ9VbFTBlcPc1LW .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eBJ9VbFTBlcPc1LW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eBJ9VbFTBlcPc1LW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eBJ9VbFTBlcPc1LW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OSI七层模型
7 应用层

HTTP/FTP/SMTP
6 表示层

加密/压缩/编码
5 会话层

连接管理
4 传输层

TCP/UDP
3 网络层

IP/路由
2 数据链路层

以太网
1 物理层

比特流传输

在实际编程中,我们主要关注应用层 (自定义协议)、传输层 (TCP/UDP Socket API)和网络层(IP地址配置)。表示层和会话层的功能通常由应用层协议(如HTTPS中的TLS)或应用框架提供。

4. 协议设计的扩展性思考

自定义协议设计需要考虑向前兼容向后兼容。通过在协议头部添加版本号字段,可以在不破坏旧客户端的情况下升级协议。序列化框架(如Protocol Buffers、JSON、MessagePack)内置了版本兼容机制,是生产环境中的推荐选择。

协议设计还需要考虑安全性 。明文传输的自定义协议容易受到中间人攻击、重放攻击等威胁。在生产环境中,应在传输层使用TLS/SSL加密,或在应用层实现加密和认证机制。


六. 总结与最佳实践

1. 核心概念回顾

通过学习,我们可以梳理出Linux网络编程的核心知识链:

  1. 地址转换inet_pton/inet_ntop处理IP地址,htons/ntohs处理端口号
  2. Socket创建socket()bind()listen()accept()(服务器)或connect()(客户端)
  3. 数据收发send() /**recv()**操作的是内核缓冲区,不是直接操作网络
  4. 连接管理:监听Socket与连接Socket分离,一个监听Socket可接受多个连接
  5. 协议设计:必须自定义应用层协议解决TCP粘包问题,推荐"长度前缀"模式
  6. 序列化:对象与字节流之间的转换,实现跨平台数据交换
  7. 分层架构:网络层、协议层、业务层分离,通过回调解耦

2. 关键设计原则

原则一:理解缓冲区机制

write()成功只表示数据进入了内核发送缓冲区,不代表数据已发送到对方。read()返回的数据可能只是对方发送数据的一部分。应用程序必须处理部分发送部分接收的情况。

原则二:正确处理粘包

TCP是流式协议,没有消息边界。任何基于TCP的应用都必须实现自定义协议来界定消息边界。长度前缀是最可靠的方式。

原则三:区分监听Socket和连接Socket

accept()返回新的文件描述符,原监听Socket继续工作。不要混淆两者,也不要在监听Socket上执行**recv()/ send()**。

原则四:采用分层架构

将网络传输、协议解析、业务逻辑分离。这不仅提高代码质量,也便于单元测试和团队协作。

原则五:注意字节序和内存对齐

网络字节序是大端序,结构体序列化时要考虑内存对齐和填充字节。使用#pragma pack或序列化库可以避免这些问题。

3. 从理论到实践

掌握这些概念后,可以构建一个完整的TCP服务器:

  1. 创建TcpServer类,封装socket()bind()listen()accept()
  2. 创建Protocol类,实现序列化、反序列化、消息解析
  3. 创建业务处理类(如Calculator),实现具体功能
  4. 使用std::function或函数指针实现层间回调
  5. 考虑使用线程池处理并发连接,或使用epoll实现高并发I/O

#mermaid-svg-UDFTvQlc8wC12VCP{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-UDFTvQlc8wC12VCP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UDFTvQlc8wC12VCP .error-icon{fill:#552222;}#mermaid-svg-UDFTvQlc8wC12VCP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UDFTvQlc8wC12VCP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UDFTvQlc8wC12VCP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UDFTvQlc8wC12VCP .marker.cross{stroke:#333333;}#mermaid-svg-UDFTvQlc8wC12VCP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UDFTvQlc8wC12VCP p{margin:0;}#mermaid-svg-UDFTvQlc8wC12VCP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UDFTvQlc8wC12VCP .cluster-label text{fill:#333;}#mermaid-svg-UDFTvQlc8wC12VCP .cluster-label span{color:#333;}#mermaid-svg-UDFTvQlc8wC12VCP .cluster-label span p{background-color:transparent;}#mermaid-svg-UDFTvQlc8wC12VCP .label text,#mermaid-svg-UDFTvQlc8wC12VCP span{fill:#333;color:#333;}#mermaid-svg-UDFTvQlc8wC12VCP .node rect,#mermaid-svg-UDFTvQlc8wC12VCP .node circle,#mermaid-svg-UDFTvQlc8wC12VCP .node ellipse,#mermaid-svg-UDFTvQlc8wC12VCP .node polygon,#mermaid-svg-UDFTvQlc8wC12VCP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UDFTvQlc8wC12VCP .rough-node .label text,#mermaid-svg-UDFTvQlc8wC12VCP .node .label text,#mermaid-svg-UDFTvQlc8wC12VCP .image-shape .label,#mermaid-svg-UDFTvQlc8wC12VCP .icon-shape .label{text-anchor:middle;}#mermaid-svg-UDFTvQlc8wC12VCP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UDFTvQlc8wC12VCP .rough-node .label,#mermaid-svg-UDFTvQlc8wC12VCP .node .label,#mermaid-svg-UDFTvQlc8wC12VCP .image-shape .label,#mermaid-svg-UDFTvQlc8wC12VCP .icon-shape .label{text-align:center;}#mermaid-svg-UDFTvQlc8wC12VCP .node.clickable{cursor:pointer;}#mermaid-svg-UDFTvQlc8wC12VCP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UDFTvQlc8wC12VCP .arrowheadPath{fill:#333333;}#mermaid-svg-UDFTvQlc8wC12VCP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UDFTvQlc8wC12VCP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UDFTvQlc8wC12VCP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UDFTvQlc8wC12VCP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UDFTvQlc8wC12VCP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UDFTvQlc8wC12VCP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UDFTvQlc8wC12VCP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UDFTvQlc8wC12VCP .cluster text{fill:#333;}#mermaid-svg-UDFTvQlc8wC12VCP .cluster span{color:#333;}#mermaid-svg-UDFTvQlc8wC12VCP 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-UDFTvQlc8wC12VCP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UDFTvQlc8wC12VCP rect.text{fill:none;stroke-width:0;}#mermaid-svg-UDFTvQlc8wC12VCP .icon-shape,#mermaid-svg-UDFTvQlc8wC12VCP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UDFTvQlc8wC12VCP .icon-shape p,#mermaid-svg-UDFTvQlc8wC12VCP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UDFTvQlc8wC12VCP .icon-shape rect,#mermaid-svg-UDFTvQlc8wC12VCP .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UDFTvQlc8wC12VCP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UDFTvQlc8wC12VCP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UDFTvQlc8wC12VCP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端发起连接
服务器accept
创建新线程/epoll事件
recv读取数据
Protocol解析消息
业务逻辑处理
Protocol序列化响应
send发送响应
继续等待/关闭连接

Linux网络编程是一个理论与实践紧密结合的领域。理解Socket API的底层原理、TCP协议的工作机制、以及操作系统对网络数据的处理方式,是编写高效、稳定网络程序的基础。通过自定义协议和分层架构,可以构建出可维护、可扩展的网络应用系统。


相关推荐
xxy222411 小时前
Linux 网络编程入门(一):从 OSI 模型到 TCP Socket 编程
网络·tcp/ip·tcp
消失的旧时光-19431 小时前
(KMP-Net进阶)第一篇:AppResult<T>——网络层到底应该 throw,还是返回统一 Result?
网络·ktor·kmp
苹果嘉尔121381 小时前
Linux系统编程——网络(TCP)
linux·运维·服务器
网安蟹佬霸2 小时前
区块链与智能合约安全实战:从Solidity审计到DeFi漏洞深度剖析
运维·前端·网络·安全·自动化·区块链·智能合约
昌原的儿子LEO2 小时前
Linux进程知识点总结
linux·服务器·c语言·数据库
koi77u2 小时前
嵌入式学习---进程与线程(1)
linux·服务器·学习
椿.湫2 小时前
kubenetes pod管理
linux·运维·服务器
敲代码还房贷2 小时前
安装wsl报错:HCS_E_HYPERV_NOT_INSTALLED
linux·python·ubuntu
今夕资源网2 小时前
NapCatQQ:把最难接的 QQ 协议层,变成一组能直接调用的接口
网络·qq·napcat·napcatqq·q协议·qq协议