Socket建立連接到底發生了什麼?

在echo伺服器的實現之中,server有兩個描述符listenfd,connfd。
listenfd用於監聽,connfd用於建立連接與通信。
首先listenfd會bind本機的IP和一個port。
然後listenfd=listen(....);
再用一個connfd=accept(listenfd,...);進行接收。
一旦client那邊發起connect(),server這邊accept()返回,這個時候socket連接就建立了。

我的問題是,1.對於第二個描述符--connfd它有沒有綁定這個IP與port,是綁定當前埠還是其他埠?
2.如果有一個消息來,那麼首先由IP地址選定了這台主機(假設IP地址+域名信息,能夠確定這台主機),根據port又確定了這個進程,那麼server怎麼知道這個消息是應該給描述符listenfd還是給connfd的呢?
是不是有一個表一樣的東西,將對方IP+對方port+對方描述符---------本方IP+本方port+本方描述符對應起來呢?

換句話說,accept返回,client與server建立連接到底發生了什麼操作?
如果只是告訴server端,client的埠號和IP的話,似乎並無法區分下一次到來的消息到底是給server哪一個描述符的?

請大家指點我一下,知道那本書裡面有講到這個的也行,萬分感謝。


提任何網路編程的問題之前,先翻一遍 W. Richard Stevens 的書。


客戶端和服務端連接的話,需要進行握手(也就是發SYN包,建立連接)。
服務端的埠(listenfd)監聽到客戶端SYN包的連接請求之後,會轉給(connectfd)與客戶端完成握手
客戶端就可以愉快的與服務端(connectfd)交流數據了。

需要注意的是listenfd只是監聽連接請求。
數據交互在connectfd。

listenfd與connectfd 所對應的tcpip狀態是不一樣的,前者是listen,後者應該establish。

還有&才能確定一個socket
---------------------------------------------------------------------
如有錯誤請指正。


謝謝大家的回答。
在去看這些書之前,我先以我想到的可能方式來回答一下。因為我看了下內核,有一個什麼虛擬文件系統以及BSD socket還有fd 系統之類的,我這裡想的是一個原理,具體的實現當然是很複雜的。

首先listenfd是有一個bind的過程的,那麼可以根據IP+port來唯一指定到這個fd。
所以開始的連接建立階段,client可以直接通過IP+port來找到listenfd。
在建立連接之後,server這邊是怎樣確定送來的消息是給哪一個fd的呢?
既然IP+port可以唯一確定fd,那麼server也可以反過來確定client那邊,server可以建立一個對應的table,裡面將信息來源的IP+port和自己的fd對應起來。

那麼接下來,一條信息從自己的port到達,就和路由查表差不多了。
首先查看,表中有沒有記錄(server的accept是可以獲得client的IP和port的),有的話就轉給對應的fd,
沒有的話就默認轉給listenfd。

雖然有不同的fd但是經由某個port建立的所有connection,都會經過這個port來傳遞之後的信息。
比如HTTP服務所有的建立連接以及之後的通信都是用的80埠。

這就是我目前想到的邏輯上的解決辦法。
我現在手裡有網路編程卷1,我去看看,如果如Justin所說的有明確描述,我會再貼出來。
-----------------------------------------------
2015/10/15更新
恩,UNP1裡面確實找到了答案。5.17節有講到。下面我來直接解答問的問題。
1.對於第二個描述符connfd它有沒有綁定這個IP與port,是綁定當前埠還是其他埠?
這個可以直接通過netstat命令來看。
假如最開始bind時的port是7070.使用的是多進程伺服器。
$netstat -a | grep 7070
你會發現,有一個7070埠在監聽,有一個7070已經連接建立了。
所以connfd就是使用的與listenfd相同的port。
2.如果有一個消息來,那麼首先由IP地址選定了這台主機(假設IP地址+域名信息,能夠確定這台主機),根據port又確定了這個進程,那麼server怎麼知道這個消息是應該給描述符listenfd還是給connfd的呢?
這個問題應該說就有問題,消息來了不是說傳給哪個套接字描述符。
而是本身信息就是靠TCP連接來傳遞的。
而TCP連接又是通過本地IP+本地port+外地IP+外地port來唯一確定的。
那麼當我們讀取,或者寫入某個套接字描述符的時候,它是描述的哪一個TCP連接,那麼信息就會在那個連接之間傳遞。


連接沒建立就找listenfd,連接建立了就找connfd, 附上一段內核代碼http://lxr.free-electrons.com/source/include/net/inet_hashtables.h#L299


推薦閱讀:

怎麼理解TCP是面向連接的,HTTP基於TCP卻是無連接的?
服務端把客戶端幾次發的數據一起接受了,是怎麼回事?socket,Tcp協議
TCP中已有SO_KEEPALIVE選項,為什麼還要在應用層加入心跳包機制??
TCP面向位元組流和報文段的關係是什麼?
怎樣實時判斷socket鏈接狀態?

TAG:程序員 | 計算機網路 | Socket | 網路編程 |