在 Socket 编程中,常见的疑问和解决方案可围绕以下核心问题展开:
一、基础概念与协议差异
-
Socket 本质与四元组标识
Socket 是网络通信的端点,包含本地 IP、端口和对端 IP、端口的四元组信息。例如,服务器通过bind()
绑定本地端口后,accept()
返回的新 Socket 会记录客户端的 IP 和端口,而不会占用新端口。这解释了为何一个端口可同时服务多个客户端 —— 协议栈通过四元组区分不同连接。 -
TCP 与 UDP 的核心区别
- 可靠性:TCP 通过三次握手、序列号、ACK 确认实现可靠传输;UDP 无连接且不保证顺序和完整性。
- 适用场景:TCP 适用于文件传输、HTTP 等需可靠性的场景;UDP 适用于实时音视频、DNS 查询等对速度敏感的场景。
-
阻塞与非阻塞模式
- 阻塞模式:
connect()
、recv()
等操作会阻塞线程,适合简单场景但性能较低。 - 非阻塞模式:结合
select
、epoll
等 I/O 复用技术,可同时处理多个连接,提升并发能力。例如,Linux 下通过fcntl(sockfd, F_SETFL, O_NONBLOCK)
设置非阻塞模式。
- 阻塞模式:
二、常见错误与调试
-
端口占用(EADDRINUSE)
原因通常是旧进程未正常关闭导致端口处于TIME_WAIT
状态。解决方案是在bind()
前调用setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))
,允许端口快速复用。 -
连接超时与阻塞
- 客户端:通过
setsockopt
设置SO_SNDTIMEO
控制connect()
超时。 - 服务器:设置
SO_RCVTIMEO
避免recv()
无限阻塞。例如:c
- 客户端:通过