1、Socket基础:从一根虚拟网线说起

各位同学好,我是你们这门课的老司机。今天咱们聊Socket,这东西说白了就是网络通信的基石。我做了这么多年后端,几乎每个高并发系统都离不开它。

你可能会问:Socket到底是个啥?别急,咱们一层层剥开。

1.1 Socket是什么?

Socket,中文叫“套接字”,但我觉得叫“网络通信的插座”更形象。你想啊,你家墙上的插座,插上电器就能通电。Socket也一样,它是应用层和传输层之间的接口,让两个程序能通过网络互相传数据。

从操作系统角度看,Socket就是一个文件描述符。Linux里“一切皆文件”,网络连接也不例外。你读写Socket,就像读写文件一样——只不过数据跑到了网络上。

核心定义:Socket是操作系统提供的一种抽象,用于实现网络通信的端点。每个Socket由IP地址和端口号唯一标识。

我记得刚入行时,有个同事把Socket理解成“一根虚拟网线”,一端连着进程A,一端连着进程B。虽然不严谨,但确实好懂。后来我教新人,也常用这个比喻。

1.2 Socket通信模型

Socket通信模型,说白了就是“客户端-服务器”模式。服务端先启动,等着别人来连;客户端主动发起连接。这个过程分几步走:

  1. 服务端创建Socket —— 调用 socket()
  2. 绑定地址和端口 —— 调用 bind()
  3. 监听连接 —— 调用 listen()
  4. 接受连接 —— 调用 accept(),阻塞等待
  5. 客户端创建Socket —— 调用 socket()
  6. 发起连接 —— 调用 connect()
  7. 数据传输 —— 双方用 send() / recv() 读写数据
  8. 关闭连接 —— 调用 close()

下面这张图把流程画清楚了:

Socket通信模型流程图 Socket 通信模型 服务端 socket() bind() 绑定端口 listen() 监听 accept() 阻塞等待 recv() / send() 客户端 socket() connect() 发起连接 send() / recv() 创建 准备连接 三次握手 双向数据传输 客户端主动连,服务端被动等

小技巧:写服务端代码时,accept() 返回的是新Socket,用于和客户端通信。原来的监听Socket继续等下一个连接。我见过新手把监听Socket拿去收发数据,结果一脸懵。

1.3 TCP与UDP的区别

Socket通信底层有两种协议:TCP和UDP。这俩的区别,我打个比方你就懂了。

TCP像打电话:先拨号(建立连接),通了之后你说一句我回一句,顺序不乱,丢了一句就重说。可靠,但慢。

UDP像寄明信片:写好地址扔邮筒,不管到没到,不管顺序。快,但可能丢。

具体差异看这张表:

特性 TCP UDP
连接方式 面向连接(先握手) 无连接(直接发)
可靠性 可靠传输,丢包重传 不可靠,可能丢包
数据顺序 保证顺序 不保证顺序
传输速度 较慢(有开销) 较快(无开销)
数据边界 流式,无边界 报文,有边界
应用场景 HTTP、FTP、SSH DNS、视频直播、游戏

我在项目中遇到过一个问题:用UDP做日志传输,结果高峰期丢包率超过10%,日志不全导致排查故障时缺关键信息。后来改成TCP,虽然慢了点,但一条日志都不丢。嗯,这里要注意:日志系统必须用TCP,除非你能接受丢日志。

避坑指南:我曾经在一个实时监控项目里,为了追求速度用了UDP。结果网络抖动时,监控数据断断续续,告警系统疯狂误报。最后老老实实切回TCP,加了个超时重试机制才稳住。选协议时,别只看性能,先想清楚能不能丢数据。

1.4 Socket与WebSocket的关系

这个问题经常有人搞混。我面试时问过不少候选人,十个有八个答不全。

Socket是操作系统层面的网络通信接口,工作在传输层。你用Java、C++、Python写的网络程序,底层调的都是Socket API。

WebSocket是应用层协议,基于TCP。它本质上是HTTP的一次升级——客户端发一个HTTP请求,告诉服务端“我要升级成WebSocket协议”,服务端同意后,双方就在同一个TCP连接上双向通信。

说白了,WebSocket是Socket的“上层应用”,专门解决浏览器和服务端实时通信的问题。传统HTTP是“请求-响应”模式,服务端不能主动推数据。WebSocket让服务端能随时“怼”数据给客户端。

看个简单的WebSocket握手过程:

客户端 → 服务端:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

服务端 → 客户端:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

握手完成后,双方就可以在同一个连接上互相发数据了。这就是WebSocket的“全双工”特性。

一句话总结:Socket是“路”,WebSocket是“车”。路可以跑各种车(TCP、UDP),WebSocket这辆车专门跑在TCP路上,为浏览器而生。

咱们这门课要做的日志追踪系统,底层用的是TCP Socket。为什么?因为日志一条都不能丢,而且需要服务端主动推送日志给客户端——这不就是WebSocket的强项吗?所以后面章节,我会带你在TCP Socket基础上,用WebSocket搭建实时日志管道。