客户端正常终止
- 进程终止的部分工作是关闭所有打开的描述符,因此客户打开的描述符由内核关闭。这导致客户TCP发送一个FIN给服务器,服务器TCP则以ACK响应,这就是TCP连接终止序列的前半部分,至此,服务器套接字处于CLOSE_WAIT状态,客户套接字则处于FIN_WAIT_2状态
异常状态处理
accept被系统调用中断
我们用术语慢系统调用 (slow system call)描述过accept函数,该术语也适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用。
适用于慢系统调用的基本规则是:当阻塞于某个慢系统调用的一个进程捕获某个信号且相应信号处理函数返回时,该系统调用可能返回一个EINTR错误。有些内核自动重启某些被中断的系统调用。不过为了便于移植,当我们编写捕获信号的程序时 (多数并发服务器捕获SIGCHLD) ,我们必须对慢系统调用返回 EINTR 有所准备。移植性问题是由早起晚睡使用的修饰词“可能”、“有些”、和对POSIX的SA_RESTAER标志的支持是可选的这一事实造成的。即使某个实现支持SA_RESTART标志,也并非所有被中断系统调用都可以自动重启。举例来说,大多数源自Berkeley的实现从不自动重启select,其中有些实现从不重启accept和recvfrom。
为了处理被中断的accept,我们把对accept的调用从for循环开始改起:
client = sizeof(cliaddr);
if( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0){
if(errno == EINTR)
continue;
else
err_sys("accept error");
}
注意,有一个函数我们不能重启: connect 。如果该函数返回 EINTR,我们就不能再次调用它,否则将