我在实现服务器发送一个网页给浏览器的功能时,发现如果只是设置了 HTTP 头中的 Connection: close,浏览器不一定会保证在收到所有数据后关闭连接。也就是说,寄希望于设置了这个字段后浏览器会主动关闭连接是不现实的,虽然大多数浏览器都遵循这个字段。
因此,实现发送数据后服务器主动关闭连接是有必要的。
如果希望 TCP 在数据发送完成后就关闭,直接 write(fd, ...) 所有所需数据后再调用 close(fd) 能实现这个效果吗?
答案是可以的。TCP 协议栈会保证所有写入到内核缓冲区的数据都被可靠地发送后,再发送 FIN 包。
也就是说,只要做到 写完再关,就能确保浏览器能完整收到所有数据。
但需要注意的是,TCP 在这里的“可靠”,并不意味着“必达”。 TCP 保证的是:要么成功发送到对端,要么网络断开或不可达。
一些要点
- 在非阻塞写场景下,很容易出现部分写(Partial Write),需要确保所有数据都被写入内核缓冲区后再关闭才是安全的。
- 默认的
close是优雅关闭,会等待所有数据发送完成后再发送FIN包。 - 如果对端提前关闭,会导致写返回
EPIPE或触发SIGPIPE,这两种情况都需要处理:应该直接关闭。