读UNP一书所作的小试验(2)

    本次的试验内容是UNP第7章:套接口选项 。

SO_REUSEADDR 套接字选项"


    在前一次的实验中,我就注意到,如果在步骤1中,不是kill掉向client提供服务的server子进程,而是kill掉监听外部连接的server 父进程的话,并不影响client与其对端的通信——这也符合在OS教材中传授的知识:"当进程被kill掉时,将其所有还在运行的子进程托管给自己的父 进程。“

    但是,问题在于,在完成了以上操作后,我尝试重新启动server进程(恢复监听),终端上输出错误提示: “bind error: Address already in use.”

   
问 题出在何处?通过netstat -an命令可以看到,之前与client建立的连接中,server子进程在port 9877上与client进行通讯,而现在要重新启动的server父进程在调用bind函数时,也要绑定在port 9987 ——实际上,每个server父进程通过调用accept函数返回的socket都继承了监听socket的参数。

    要解决这个问题,就需要在执行bind函数前,对套接字设置
SO_REUSEADDR属性,关于该属性的具体描述参见书中p179页。
   
    试验代码(对tcpserv04.c进行修改)


   ......................

       listenfd 
=  Socket(AF_INET ,  SOCK_STREAM ,   0 );

    int enable
=1;
                                  if(  setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&enable,sizeof(enable) ) <0 )
        printf("failed to setup the SO_REUSEADDR option "
);

    Bind(listenfd
,  (SA  * & servaddr ,   sizeof (servaddr));


"SO_LINGER 套接口选项“

   
该选项对close()函数所执行的操作进行设置。缺省情况下,close()函数会立即返回至调用者;系统试图将滞留在socket的发送缓冲区中的数据发送,并开始正常的TCP四分组连接终止序列。

    在试验1中,如果client正常退出,使用netstat -an命令,可以看到client的socket状态为TIME_WAIT。

    SO
_LINGER选项允许我们修改close()函数的缺省操作。其中的一种可能是TCP丢弃滞留在socket的发送缓冲区中的所有数据,并向对端发送RST,不经过通常的TCP四分组连接终止序列,就直接关闭连接。

    对试验1中的tcpcli01.c进行如下修改

    struct linger lin;
    lin.l_onoff=1;
    lin.l_linger=0;
    setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&lin,sizeof
(lin) );

    
exit ( 0 );

    再启动server和client,连接建立后,client正常退出,此时执行netstat -an命令,可以看到输出结果中不再有处于 TIME_WAIT状态的client socket ——该socket对应的TCP连接已彻底关闭。


 

你可能感兴趣的:(socket,Stream,server,tcp,kill,通讯)