Unix网络编程-客户端和服务端不同的终止状态

正常终止

  1. 信号处理
  2. 回收子进程
  3. 处理被中断的慢系统调用

accept返回前终止

在完成三次握手和accept返回之间(这是一个很小的间隔),客户端重发了RST报文,导致accept失败。这个时候的connect还是可以复用的,所以只要重新连接就行了。

通过套接字选项可以设置RST报文。

此时Posix下errno值会被设置成ECONNABORTED。

因为这个错误是非致命的,所以可以重新启动accept。

只要处理这个错误,并再循环执行accept就可以了。

服务器进程终止

进程终止与主机崩溃不同。

服务进程终止,进程会发送FIN报文,使得TCP处于半关闭状态(服务器到客户端的连接关闭,客户端到服务端的通信还可以继续)。

如果我们的客户端程序没有处理收到的FIN报,而是继续执行客户端任务,比如说继续发送数据和接受数据,就会出现问题:

  1. 如果继续写这个套接字,就会收到服务端的RST报文,这个报文会对下一次写造成影响
  2. 因为收到的是RST报文,而不是目的文本,所以read函数会返回错误,这可能导致客户端进程关闭

这样的解决方法可以是使用IO多路复用,比如poll或epoll,来同时监听套接字和read,当套接字发生FIN的时候,去做相应的操作,而不是write之后直接去read。

SIGPIPE信号:

当进程收到一个RST报文的时候,会发送一个SIGPIPE信号,无论对这个信号是忽略,默认,还是捕捉,往这个套接字上的写操作都会触发EPIPE错误

注意:这是再写,才会触发这个EPIPE错误,那么如果你想通过这个错误来进行相应的处理,你最少需要写两次,第一次触发SIGPIPE信号,第二次引发EPIPE错误。

如果是处理SIGPIPE信号,那么可以做一些我们想要的操作,但是我们不知道是哪个write引发的。
如果想知道是哪个write引发的,就只能去引发EPIPE错误,并处理这个错误。

服务器主机崩溃或客户发送的数据不可达

服务器主机崩溃,不发送任何东西。

如果是目的主机崩溃:这样客户端不知道对方是否挂掉了,就会一直重传报文,一直到内核规定的时间(很长,几分钟),并返回一个错误;ETIMEDOUT。

如果是中间路由崩溃:路由会发送一个ICMP报文,并在客户端引发EHOSTUNREACH 或 ENETUNREACH错误。

如果不想等待几分钟,我们可以手动设置read的超时时间。

或者主动获得服务器的崩溃信息:SO_KEEPALIVE套接字选项或心跳包。

服务器主机崩溃后重启

重启之后,服务器丢失所有TCP信息。当服务器再次收到客户端的报文的时候,就会回复RST报文,表示想重新建立连接。

如果客户端正阻塞读就会返回ECONNRESET错误。

服务器主机关机

服务器进程正在运行,但是主机关机。

init进程先对所有进程发送SIGTERM信号(各进程可以捕获此信号,并马上善后),然后再对所有进程发送SIGKILL信号(此信号不能捕获,杀死所有进程)。

就会跟第三种情况一样。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙子砰砰枪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值