1. Socket 基础概念回顾

做网络排查这么多年,我见过太多人一上来就抓包、调参数,结果连 Socket 到底是什么都没搞清楚。说白了,Socket 就是操作系统提供的一个编程接口,让两个程序能在网络上互相通信。你想想看,没有 Socket,你的浏览器怎么跟服务器要数据?你的怎么发消息?

1.1 什么是 Socket

Socket 这个词直译过来是「插座」。这个比喻其实挺形象的——你把一个程序插到网络上,它就能跟另一个插到网络上的程序通话。从技术角度讲,Socket 是应用层与传输层之间的抽象层,它封装了 IP 地址和端口号。

核心要点:Socket = IP 地址 + 端口号 + 协议类型。这三者唯一确定一个通信端点。

我记得刚入行时,有个老工程师跟我说过一句话:「Socket 就是门,数据就是人,门开对了人才能进出。」后来我自己排查故障时,发现很多问题确实就出在这个「门」上——端口被占用了、IP 绑错了、协议不匹配。

1.2 Socket 通信模型

Socket 通信模型其实不复杂。我习惯把它分成三个角色:客户端、服务端、网络通道。服务端先启动,等着别人来找它;客户端主动发起连接;网络通道负责把数据搬来搬去。

下面这张图是我自己总结的 Socket 通信流程,你一看就明白:

Socket 通信模型流程图 服务端 socket() 创建 bind() 绑定端口 listen() 监听 accept() 接受连接 recv() / send() 通信 close() 关闭 客户端 socket() 创建 connect() 发起连接 send() / recv() 通信 close() 关闭 TCP 三次握手 连接建立 数据双向传输 TCP 四次挥手 TCP 面向连接,UDP 无连接,流程不同

这个流程看着简单,但实际排查时每一步都可能出问题。我曾经遇到过一个 case,服务端 listen 之后一直 accept 不到连接,查了半天发现是 bind 的端口被防火墙拦截了。嗯,这种坑踩过一次就记住了。

1.3 TCP 与 UDP 的区别

这是面试常考题,也是实际排查中必须分清楚的东西。我直接给你列个表,对比着看:

对比维度 TCP UDP
连接方式 面向连接,需三次握手 无连接,直接发数据
可靠性 可靠传输,有重传机制 不可靠,丢包不重传
数据顺序 保证数据按序到达 不保证顺序
传输效率 较低,有确认和拥塞控制 较高,无额外开销
应用场景 HTTP、FTP、SSH、数据库 DNS、视频流、游戏、VoIP
报文边界 流式传输,无边界 保留报文边界

实战小技巧:我排查问题时,第一件事就是确认用的是 TCP 还是 UDP。如果是 TCP,重点看连接状态和重传;如果是 UDP,重点看丢包率和报文大小。方向错了,查半天都是白费。

1.4 为什么这两个协议差别这么大?

你想想看,TCP 就像打电话——先拨号、等待对方接听、确认通了才开始说话,说完还要挂断。这个过程保证了可靠性,但代价就是慢。UDP 呢?就像对讲机——你按下按钮直接说,不管对方有没有在听。快是快了,但对方可能漏掉一半内容。

我记得有一次排查视频会议卡顿的问题。客户坚持认为是网络带宽不够,我抓包一看,发现用的是 TCP 传输视频流。TCP 的拥塞控制导致视频数据频繁重传,画面自然卡。后来改成 UDP + 应用层纠错,问题就解决了。所以选对协议,比调优参数更重要。

1.5 Socket 编程中的关键数据结构

写 Socket 程序时,有几个结构体你必须烂熟于心。我当年背这些结构体背到吐,但后来发现,排查问题时这些知识真能救命。

// IPv4 地址结构(最常用)
struct sockaddr_in {
    sa_family_t    sin_family;   // AF_INET
    in_port_t      sin_port;     // 端口号(网络字节序)
    struct in_addr sin_addr;     // IP 地址
    char           sin_zero[8];  // 填充字节
};

// 通用地址结构
struct sockaddr {
    sa_family_t sa_family;   // 地址族
    char        sa_data[14]; // 地址数据
};

⚠️ 常见坑点:端口号和 IP 地址必须转换成网络字节序!我见过太多新手直接用 htons() 和 inet_pton() 搞反了,结果 bind 成功但客户端连不上。曾经有个同事排查了三天,最后发现是字节序问题——这种低级错误最让人崩溃。

1.6 我总结的 Socket 故障排查第一原则

做排查这么多年,我总结了一条铁律:先确认基础,再怀疑复杂。很多人一上来就怀疑内核参数、怀疑驱动、怀疑硬件,其实 80% 的问题出在最基础的地方:

  • 端口是否被占用?——用 netstat -tlnp 或 ss -tlnp 看一眼
  • IP 是否绑定正确?——0.0.0.0 和 127.0.0.1 差别大了
  • 防火墙有没有拦截?——iptables -L -n 检查一下
  • 协议是否匹配?——服务端用 TCP,客户端用 UDP,神仙也连不上

嗯,这一章的内容就到这里。基础打牢了,后面讲具体故障场景时你才能跟得上。记住我说的:Socket 没那么玄乎,它就是程序之间的一根「网线」,你只要搞清楚它怎么接、怎么通、怎么断,排查问题就有方向了。