在写tcp服务器代码的时候,关闭服务端进程的时候再次打开会发现bind error,通过netstat查看发现当前端口被占用,查阅Unp发现是TIME_WAIT状态,tcp在断开连接的时候,主动断开连接的一端会在发最后一个ACK之后,等待一段时间,以防止这个ACK丢失。UNP中总结了TIME_WAIT存在的两点理由:(1)可靠的实现TCP全双工连接的终止,(2)允许老的重复分节在网络中消逝。

第一点理由就是在另一端超时并重发最后的FIN时,主动关闭的这一端可以重新发送ACK以成功关闭。第二点时因为主动关闭连接的一端如果时服务端,那么对于服务端而言,端口号时绑定的,因此如果没有Time_WAIT,在上次连接关闭之后,进行下次连接时。由于ip地址,端口号没有发生变化,那么后一个连接称为前一个连接的化身,tcp必须防止来自某个连接的老的重复的分组在该连接已终止后再现。

TIME_WAIT的时间是2MSL,也就是最长分节生命期的2倍,任何TCP的实现都需要为MSL选择一个值,一般为30s~2min。

TIME_WAIT状态确实十分重要,确保了TCP的可靠传输,然而对于开发者来说,每次主动关闭服务端都要重新等待两三分钟的TIME_WAIT或是kill掉进程都是十分麻烦的,SO_REUSEADDR是解决这个问题的办法,这个选项会允许对处于TIME_WAIT等待的端口进行赋值。


#include <sys/socket.h>
int setsockopt(int sock, int level, int optname, const void* optval, socklen_t optlen);

int getsockopt(int sock, int level, int optname, const void* optval, socklen_t* optlen);

 这是socket选项的函数原型,其中level代表可选的协议层,值为SOL_SOCKET时,有SO_REUSEADDR选项

//option为1时,即可
int option = 1;
int optlen = sizeof(option);
setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);

49098为client的端口,因此可以发现客户端也有TIMEWAIT状态,不过因为客户端为随机分配端口,因此不会影响下次TCP的连接