【unix网络编程卷一】tcp客户端/服务器连接终止的各种情况

tcp协议中,不止需要知道客户端/服务器程序正常终止连接时会发生什么,还需要知道各种异常终止的情况

客户端和服务器建立的流程图如下:

 

 当我们结束进程时,会调用close函数或者exit函数,就会关闭所打开的套接字,这个时候就会往对端发送fin,从而进行正常的4次挥手过程,双方正常关闭连接,这时没有任何异常的情况,但是在实际的使用场景中,我么还需要考虑各种各样的异常情况

 

1、当处于正常连接中的服务器主机崩溃时,一直不重启

当服务器主机崩溃时,已有的网络上已经发送不出任何东西,假如客户端服务器的场景是:

客户端write消息给服务器, 等待服务器收到消息时将消息发送回客户端 

客户端已经调用完write函数将消息写入内核,内核将数据发送给服务器端,客户端现在正阻塞在read函数上,等待服务器的消息回来,但是这时候服务器已经崩溃,不会 响应信息,通过抓包可以看见,客户端持续的重传数据给服务器,希望服务器返回一个ack回来,重传该数据大概12次,持续将近9分钟,当客户端最后放弃重传时,read将返回一个错误,如果 服务器一直崩溃, 对客户端发送的数据没有响应,最后会返回一个,ETIMEDOUT错误,如果是中间的 路由器判定 服务器不可达,将会响应一个“destination unreachable” 的ICMP消息,返回的错误码是EHOSTUNREACH或ENETUNREACH,正常使用中我们不会等待9分钟,所以要设置timeout时间

 2、当处于正常连接的服务器崩溃后然后重启

当服务器崩溃后重启时,它的tcp已经丢失了之前的所有连接信息,因此收到客户端发送的信息时将响应一个RST(复位),由于此时客户端正阻塞于read等待服务器的回答,收到RST时会导致该系统调用返回ECONNRESET错误

3、 当服务器主机关机时

Unix系统关机时,init进程通常向所有的进程发送SIGTERM信号(可捕获),然后等待5到 20s过后,给所有仍在运行的进程发送SIGKILL信号(不能被捕获),所有的进程都会被终止,服务器打开的描述符都会被关闭, 会向客户端发送fin,客户端就会向服务器发送ack,进入半双工状态,如果这时 客户端还向服务器发送数据,服务器将响应一个RST

4、 服务器多进程的情况

如果是多进程的情况, 父进程accpet返回后将连接套接字交由子进程处理,父进程重新阻塞在accept,当服务器子进程阻塞于read时,如果这时候客户端终止,向服务器发送fin,子进程收到fin后返回ack,进入close_wait状态,当子进程终止时,会向服务器发送一个SIGCHID信号,如果父进程不处理这个信号,该信号默认被忽略,子进程就进入僵死状态(僵尸进程,当父进程退出时交由init进程接管,才会被清理,实际情况中我们的父进程一直是while循环accept,不会轻易退出,大量的僵尸进程会耗尽进程资源),在我们的程序中需要捕捉这个信号,不然会占用资源

这里说一下父进程回收子进程时最好使用waitpid,因为如果信号处理函数调用wait 回收子进程时, 如果没有已终止的子进程,wait会阻塞到现有的子进程第一个终止为止,这就会造成如果大量的客户端同时关闭,服务器父进程产生的子进程同一时间向父进程发送SIGCHID信号,如果这时候wait时阻塞的,还是处于信号处理流程中,那会有大量的信号不会被处理,还是会产生僵尸进程(unix中,一个信号处于信号处理函数流程中,该信号是会被阻塞的,如果一个信号在阻塞期间产生了一次或多次,这个信号在解阻塞后通常只递交一次 ,所以不是每个信号都能处理到,就会产生僵尸进程)

而pid_t waitpid(pid_t pid, int *statloc, int options)的参数options可以指定为WNOHANG,用于告知内核在没有终止的子进程时不阻塞 

父进程捕捉该信号时,是阻塞在accept函数中的,接收到SIGCHID信号时,可能会返回一个EINTR错误,所以我们需要处理这个错误,让父进程重新accept(这时慢系统调用(指可能永远阻塞的系统调用)的一个特点,当阻塞于某个慢系统调用的一个进程捕捉到某个信号且相应的信号处理函数返回时,可能会返回EINTR,所以正常情况下read,write这些系统调用都需要处理这个错误,不过connect不能再次调用,当connect返回EINTR时再次调用会立即返回错误)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值