TCP Socket通過(Source IP, Source Port, Dest IP, Dest Port)來唯一標(biāo)識(shí)。 所以多個(gè)client可以連接到同一個(gè)Server的同一個(gè)port。 根據(jù)TCP的流程,TCP服務(wù)端首先會(huì)生成一個(gè)listen socket, 綁定端口,然后監(jiān)聽該端口,當(dāng)有連接到來,accept之后會(huì)生成新的connect socket。那么我就有疑問了,listen socket 和 connect socket 是使用同一個(gè)端口嗎? 如果是,客戶端發(fā)過來的數(shù)據(jù),傳輸層接收到以后,OS怎么知道接下來由哪個(gè)Socket來接收?
我找了一圈google,終于在這篇文章找到了答案。
Server Socket List:
local address | local port | foreign address | foreign port | listen?
-- bind
0.0.0.0 1234 0 0
-- listen
0.0.0.0 1234 0 0 YES
-- connect
0.0.0.0 1234 0 0 YES
192.168.15.67 1234 135.250.68.43 7801
注意連接這一步,第一行是listen socket,第二行是connect socket。當(dāng)客戶端發(fā)送連接請(qǐng)求時(shí),將server address和port傳遞給connect方法,connect會(huì)向服務(wù)端發(fā)送connect control message。服務(wù)端收到connect control message之后,將掃描PCB表,是否端口符合,外部地址匹配(0匹配一切),并且socket是否在監(jiān)聽狀態(tài)。自然listen socket是符合的,當(dāng)向listen socket 發(fā)送了連接請(qǐng)求后,經(jīng)過幾個(gè)來回,一個(gè)新的socket創(chuàng)建出來,這個(gè)新的socket完整的描述了客戶端與服務(wù)端的連接信息,并且標(biāo)明了不是用來監(jiān)聽。接下來,服務(wù)端會(huì)向客戶端發(fā)送一條ACK消息,消息本身就帶了服務(wù)端的地址和端口(客戶端雖然向connect傳遞了參數(shù),但本地的socket并不知道server的具體地址)。當(dāng)客戶端接收到該信息時(shí),也更新了本地的Socket,之后就可以互相發(fā)送數(shù)據(jù)了。
Client Socket List:
local address | local port | foreign address | foreign port | listen?
-- bind
0.0.0.0 7801 0 0
-- listen
0.0.0.0 7801 0 0
-- connect (send a control message to server, receive ACK)
0.0.0.0 7801 192.168.15.67 1234
可以看出在connect沒有完成前,服務(wù)端和客戶端的socket都是不完整的,這個(gè)階段之間往返的控制消息有可能是OS直接發(fā)給傳輸層,不必經(jīng)過socket。另外,server的listen socket由于不處理實(shí)際數(shù)據(jù),可以良好的一直運(yùn)轉(zhuǎn)下去。進(jìn)程本身可以創(chuàng)建共享端口的多個(gè)Socket,而多個(gè)進(jìn)程這么做不是不可以,但會(huì)有問題,因?yàn)閿?shù)據(jù)只能發(fā)送給一個(gè)進(jìn)程。