UNIX網路程式設計學習(11)--分析TCP回射服務+客戶程式:正常啟動與正常終止

pengfoo發表於2012-03-26

分析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 -

後續,我們將學習去清理僵死程式。

 

 

 

 

 

 

 

 

 

 

 

 

 


 

相關文章