撇开防火墙影响,不同平台 TCP 协议栈对连接表现不一样。
服务端状态 | 平台 | 现象 | 协议栈行为 |
---|---|---|---|
端口未监听 | Win/Linux | 连接拒绝 | 对 syn 包回应 reet 包 |
连接已满 | Linux | 连接超时 | syn 包无回包 |
连接已满 | Windows | 连接拒绝 | syn 包回包 Reset |
端口已关闭 | Win/Linux | reset by peer | 协议栈已不维护该连接,对新数据包回应 reset |
几个有趣的例子
现象:客户端连接 Windows 服务端,报告连接拒绝。
分析
如果来自 Linux 世界的人,可能以为 Windows 服务端程序退出了,没有监听端口。
但是实际上也可能是 Windows 服务端处理不过来。程序还是活着的。
客户端 send 后马上 recv,存在一定概率发生 reset by peer
分析
异常发生在 recv 上,但是 recv 本身不发送数据包,为什么会触发异常?
因此异常只可能发生在 send 阶段。
我们从微观来看,send 这个 syscall 把数据丢给协议栈就返回了,实际上还没发送到服务端。
如果这个时候服务端因为某些原因不维护了这个连接:
- 服务端断电重启了
- 服务端关闭了这个 socket
那么,这个时候协议栈发送未完成的数据会导致服务端回应 reset 包,如果当时用户正好跑到 recv,用户就看到了这个 reset by peer 的错误。实际上这个错误是由 send 触发的,只是报错到了 recv 代码阶段。其他还有 keepalive 等也会触发类似错误,不一一列举。