如果是服务端程序重启或者出现 bug 崩溃,这时服务端会主动断开连接,如下图所示

image.png

因为要等待 2 个 MSL 才能最终释放连接,所以如果这个时候程序马上启动,就会出现Address already in use错误。要过 1 分钟以后才可以启动成功。如果你写了一个 web 服务器,崩溃以后被脚本自动拉起失败,需要等一分钟才正常,运维可能要骂娘了。

为什么需要 SO_REUSEADDR 参数

如果前后两个应用是同一个程序, 那么可以开启该选项.

我们都知道 TCP 连接由四元组唯一确定。形式如下

{local-ip-address:local-port , foreign-ip-address:foreign-port}

image.png

TCP 要求这样的四元组必须是唯一的,但大多数操作系统的实现要求更加严格,只要还有连接在使用这个本地端口,则本地端口不能被重用(bind 调用失败)

启用 SO_REUSEADDR 套接字选项可以解除这个限制,默认情况下这个值都为 0,表示关闭。为了保险起见,写 TCP、HTTP 服务一定要主动设置这个参数为 1。

是不是只有处于 TIME_WAIT 才允许端口复用?

不一定是要处于 TIME_WAIT 才允许端口复用的

为什么通常不会在客户端上出现

因为客户端都是用的临时端口,这些临时端口与处于 TIME_WAIT 状态的端口恰好相同的可能性不大,就算相同换一个新的临时端口就好了。