Post

《TCP/IP 网络编程》学习记录

简要记录我的《TCP/IP 网络编程》学习过程。

《TCP/IP 网络编程》学习记录

Chapter 1

Section 1.1

run hello_server.c run hello_client.c

Section 1.2

run low_open.c run low_read.c run fd_seri.c

Chapter 2

Section 2.1

run tcp_server.c run tcp_client.c

Chapter 3

Section 3.3

run endian_conv.c

Section 3.4

run inet_addr.c run inet_aton.c run inet_ntoa.c

Chapter 4

Section 4.3

run echo_server.c run echo_client.c 1 run echo_client.c 2 run echo_client.c 3

Chapter 5

Section 5.1

run op_server.c run op_client.c

Error

bind() error

问题描述

短时间内连续两次运行 ./hserver 9190 会报错 bind() error bind() error

问题原因

之前运行过服务器,TCP 端口需要一段时间才能完全释放。等待1-2分钟再重试既可。这是典型的 TCP 端口 TIME_WAIT 状态 问题。

当关闭服务器程序后,TCP 套接字会进入 TIME_WAIT 状态,通常持续 1-2 分钟。在这个状态下:

  • 操作系统保留端口号,确保网络中所有数据包都已完成传输
  • 相同的 IP:端口组合暂时无法立即重用

解决方案

方法1:设置 SO_REUSEADDR 套接字选项

在 bind() 之前添加:

1
2
3
// 在 socket() 之后,bind() 之前添加:
int optval = 1;
setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

完整代码示例:

1
2
3
4
5
6
7
8
9
10
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if (serv_sock == -1)
    error_handling("socket() error");

// 添加这3行:允许地址重用
int optval = 1;
setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

memset(&serv_addr, 0, sizeof(serv_addr));
// ... 其余代码不变
方法2:等待 TIME_WAIT 超时

等待 1-2 分钟端口自动释放。

方法3:使用不同的端口号
1
2
./hserver 9191
./hserver 9192

验证

验证 bind() error

Note

SOCK_STREAM 与 SOCK_DGRAM

对比项SOCK_STREAMSOCK_DGRAM
协议TCP(传输控制协议)UDP(用户数据报协议)
连接方式面向连接(需建立连接)无连接(无需建立连接)
传输方式字节流(数据连续、无边界)数据报(以独立数据包发送)
可靠性可靠,保证顺序、无丢包不可靠,可能丢包、乱序
传输速度较慢(因确认与重传机制)较快(无握手、无重传)
适用场景文件传输、HTTP、远程登录等实时音视频、广播、DNS 查询等
This post is licensed under CC BY 4.0 by the author.