- pipe:
read(fd, buf, sizeof(buf)); write(fd, buf, sizeof(buf));
- 读管道时写端已关闭 —— 读完所有数据,再读返回 0
- 写管道时读端已关闭 —— `SIGPIPE` 信号,进程终止
(__NOTE__:这和读/写一个已关闭的文件描述符不是一回事!)
- 网络套接字
- 读一个对方已经关闭的套接字
- 如果对方读缓冲区已空:
- 如果读缓冲区还有数据,读出所有数据,返回读到的 bytes 数
- 如果读缓冲区已无数据,直接返回 0
- 如果对方读缓冲区还有数据:
A端 调用 `close(fd)` ,此时如果 A 的读缓冲区还有数据,那么 A 发给 B 一个 Reset 包强制关闭连接:A---RST-->B;B 端再次调用 `recv()` 时,喜提 `return -1, errno = ECONNERESET`
解决办法:用 `shutdown(fd, SHUT_RDWR)` 代替 `close(fd)`
- 写一个对方已经关闭的套接字
- 第一次写,正常
- 再次写,`SIGPIPE` 请
`shutdown(fd, SHUT_WR)` 触发发送 FIN 报文,而 `SHUT_RD` 不发送。
`shutdown(fd, SHUT_WR)` 即单方面关闭写传送,本端 shutdown 后进入 FIN_WAIT 状态,仍可继续 `recv` 接收数据;对端收到 FIN 报文后立即返回 ack[.],如果也准备关闭则直接返回 [F.],否则进入 CLOSE_WAIT 状态继续 send 发包,直到自己把要发的发完,再发 [F.] 转入 LAST_ACK 状态。