UNIX网络编程学习(11)--分析TCP回射服务+客户程序:正常启动与正常终止

分析TCP回射服务+客户程序:
启动服务器程序后,netstat -a,后终端出现:
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State     
tcp        0      0 *:9877                  *:*                     LISTEN    

其中本地端口为9877正是我们启动的服务器应用


启动我们的客户/服务器程序对,
通过三次握手,连接建立。接着发生的步骤:
1.客户端调用str_cli 函数,该函数将阻塞于fgets调用。因为我们还没键入一行文本
2.当服务器中的accept返回时,服务器调用fork,再由子进程调用str_echo。str_echo调用readline,readline调用read,
read在等待客户送入一行文本期间阻塞
3.另一方面,服务器父进程再次调用accept并阻塞,等待下一个客户连接


终端netstat -a后,终端显示:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State     
tcp        0      0 *:9877                  *:*                     LISTEN    
tcp        0      0 localhost.localdoma:ipp *:*                     LISTEN    
tcp        0      0 *:daytime               *:*                     LISTEN    
tcp        0      0 localhost.localdo:55817 localhost.localdom:9877 ESTABLISHED
tcp        0      0 localhost.localdom:9877 localhost.localdo:55817 ESTABLISHED
tcp6       0      0 ubuntu:ipp              [::]:*                  LISTEN    
udp        0      0 *:52444                 *:*    

 第二个ESTABLISHED的本地端口号为9877,可判断出其对应服务器子进程的套接口;第一个ESTABLISHED的本地端口号是55817,
可判断出其对应客户进程的套接口。

         
zhouzhou@ubuntu:~/Desktop$ ps -a -o pid,ppid,stat,args,wchan
  PID  PPID STAT COMMAND                     WCHAN
 8780  8779 S+   sh -c LD_LIBRARY_PATH=$LD_L wait
 8781  8780 S+   /home/fupeng/Desktop/codebl inet_csk_wait_for_connect
 8993  8992 S+   sh -c LD_LIBRARY_PATH=$LD_L wait
 8994  8993 S+   /home/fupeng/Desktop/codebl n_tty_read
 8995  8781 S+   /home/fupeng/Desktop/codebl sk_wait_data
 9194  4449 R+   ps -a -o pid,ppid,stat,args -

简略:

  PID  PPID STAT COMMAND                     WCHAN
 
 8781  8780 S+   /home/fupeng/Desktop/codebl inet_csk_wait_for_connect   判断为父进程
 
 8994  8993 S+   /home/fupeng/Desktop/codebl n_tty_read                  判断为客户程序
 8995  8781 S+   /home/fupeng/Desktop/codebl sk_wait_data   判断为子进程


服务器和客户程序都启动时:

zhouzhou@ubuntu:~/Desktop$ netstat -a | grep 9877
tcp        0      0 *:9877                  *:*                     LISTEN    
tcp        0      0 localhost.localdom:9877 localhost.localdo:54491 ESTABLISHED
tcp        0      0 localhost.localdo:54491 localhost.localdom:9877 ESTABLISHED

客户端(ctrl+d结束后,),会经历如下:客户端会经历一个TIME_WAIT  状态。
zhouzhou@ubuntu:~/Desktop$ netstat -a | grep 9877
tcp        0      0 *:9877                  *:*                     LISTEN    
tcp        0      0 localhost.localdo:54491 localhost.localdom:9877 TIME_WAIT 
zhouzhou@ubuntu:~/Desktop$ netstat -a | grep 9877
tcp        0      0 *:9877                  *:*                     LISTEN

当前连接的客户端(本地端口号)进入了TIME_WAIT状态,而监听服务器仍在等待另一个客户连接。
正常终止客户和服务器的步骤:
1.当我们键入<Ctr-D>EOF字符时,fgets返回一个空指针,str_cli函数返回。
2.当str_cli返回到客户的main函数时,main通过exit终止。
3.进程终止时的一部分操作是关闭所有打开的描述字,客户打开的描述字由内核关闭。这导致客户tcp发送一个FIN给服务器,服务器TCP则以ACK响应,这是TCP连接终止的前半部操作。至此,服务器接口处于CLOSE_WAIT状态,客户套接口处于FIN_WAIT_2状态。
4.当服务器TCP接受FIN时,服务器子进程阻塞于readline调用,于是readline返回0.这导致str_echo函数返回服务器子进程的main函数
5.服务器子进程通过调用exit来终止。
6.服务器子进程打开的所有描述字随之关闭。由子进程关闭已连接套接口引发TCP连接终止序列最后两个分节:一个是从服务器到客户的FIN;另一个是从客户到服务器的ACK。至此,连接完全终止,客户套接口进入TIME_WAIT状态
7.进程终止处理的另一部分内容是:在服务器子进程终止时,会给父进程发送一个SIGCHLD信号。该信号的缺省行为被忽略。


这时,我们查看进程,子进程进入僵尸状态。
zhouzhou@ubuntu:~/Desktop$ ps -a -o pid,ppid,stat,args,wchan
  PID  PPID STAT COMMAND                     WCHAN
 8780  8779 S+   sh -c LD_LIBRARY_PATH=$LD_L wait
 8781  8780 S+   /home/fupeng/Desktop/codebl inet_csk_wait_for_connect
 8995  8781 Z+   [unp2] <defunct>            exit
 9355  8781 Z+   [unp2] <defunct>            exit
 9581  4449 R+   ps -a -o pid,ppid,stat,args -

后续,我们将学习去清理僵死进程。

 

 

 

 

 

 

 

 

 

 

 

 

 


 

你可能感兴趣的:(编程,网络,unix,tcp,ubuntu,服务器)