1. 程式人生 > >socket中close()和shutdown()區別

socket中close()和shutdown()區別

基本TCP程式socket函式

這裡寫圖片描述

併發伺服器

Unix中編寫併發伺服器最簡單的辦法是fork一個子程序來服務每個客戶。
當一個連線建立時,accept返回,伺服器接著呼叫fork,然後由子程序服務客戶(通過已連線的套接字connfd),父程序則等待另一個連線(通過監聽套接字listenfd)。新的客戶由子程序提供服務,父程序就關閉已連線套接字。

如圖:
1、伺服器接收了一個客戶請求
這裡寫圖片描述
2、伺服器呼叫fork,此時listenfd和connfd這兩個描述符都在父程序和子程序之間共享(被複制)。
這裡寫圖片描述
3、父程序關閉已連線套接字(connfd),由子程序關閉監聽套接字(listenfd)
這裡寫圖片描述

最終子程序處理與客戶的連線,父程序則可以在監聽套接字上在此呼叫accept來處理下一個客戶連線。

close函式

close函式是用來關閉套接字

int close(int sockfd);

成功返回0,出錯為-1

關閉已連線的套接字只是導致相應描述符的引用計數減1,如果引用計數扔大於0,這個close呼叫並不會讓TCP連線上傳送一個FIN。如果確實像傳送一個FIN,可以用shutdown函式。

回到剛剛併發伺服器的過程,第二步fork返回後,connfd和listenfd的引用計數均為2。第三步,父程序close套接字connfd,子程序close套接字listenfd後,connfd和listenfd的引用計數均為1。而該套接字真正的關閉是等於0才發生的。

需要注意的是第三步如果父程序對每個accept返回的已連線套接字connfd都不呼叫close,那麼父程序最終將耗盡可用描述符,而且沒有一個客戶連線會被終止。因為子程序關閉connfd時,它的引用計數將由2減為1,因為父程序永不關閉任何已連線套接字。

shutdown函式

int shutdown(int sockfd,int howto);

成功返回0,出錯返回-1

該函式的行為依賴howto引數的值:

  • SHUT_RD
    套接字中不再有資料可接收,而且套接字接收緩衝區中的現有資料都被丟棄。

  • SHUT_WR
    對於TCP套接字,稱為半關閉(half-close)。當前在套接字傳送緩衝區中的資料將被髮送掉,後跟TCP的正常連線終止序列。(不管套接字的引用計數是否等於0)

  • SHUT_RDWR
    等於呼叫shutdown函式兩次,連線的讀半部和寫半部都關閉。

區別

  • close把描述符的引用計數減1,僅在該計數變為0時關閉套接字。shutdown可以不管引用計數就激發TCP的正常連線終止序列

  • close終止讀和寫兩個方向的資料傳送。TCP是全雙工的,有時候需要告知對方已經完成了資料傳送,即使對方仍有資料要傳送給我們。