1. 程式人生 > >linux socket 多進程使用類包裝socket的關閉問題

linux socket 多進程使用類包裝socket的關閉問題

就是 col scl block 抓包 end 產生 內存 margin

  在寫計算機網絡課設的時候,需要用socket寫一個多線程的服務器,直接用fork寫成了多進程。起初運行的時候覺得沒什麽問題,抓包看了一下發現,客戶端和服務器之間的socket並沒有關閉。

技術分享圖片

  從上圖可以看出,只有兩次揮手單向的關閉。

  經過查找資料,發現是多進程時內存復制,對socket文件產生了第二次的引用,必須關閉所有的引用才能觸發socket關閉。

Socket *clientSock = ss.sAccept();
pid = fork();
if (!pid) {
    time_t serverTime = time(0);
    char str[4
]; memcpy(str, &serverTime, sizeof(time_t)); clientSock->sendTo(str); clientSock->sClose(); break; } else{ clientSock->sClose(); }

  在主進程和子進程中都關閉socket後,後,可以看到抓包結果中,完成了四次揮手,socket成功關閉

技術分享圖片  

  以下是猜想,沒有驗證:

  那麽問題就來了,多進程中,子進程會把父進程的堆空間復制一份,也就是說,主進程堆空間中的Socket對象會被復制一份在子進程中,但是在我的代碼中是使用一個指針指向這個對象,子進程中復制的指針也指向主進程的Socket對象,而子進程中的Socket對象無法被調用。

技術分享圖片

  在這個例子中,子進程中的指針應該是指向主進程Socket對象的,所以子進程和主進程中的關閉都是對主進程中Socket進行關閉,而沒有對真正引用了文件的Socket對象副本進行關閉,也就是說,子進程創建後,對相同一個Socket對象進行兩次關閉,也能成功將sock文件的所有引用關閉。

  這裏是我的一個猜想,沒有經過驗證:

  系統用進程和文件描述符唯一確定一個文件,由於子進程內存復制了主進程,文件描述符應該相同,所以,在子進程調用主進程對象的關閉時,系統用子進程的進程號和主進程的文件描述符,確定了socket文件,成功關閉了socket。

linux socket 多進程使用類包裝socket的關閉問題