我的程序開(kāi)了一個(gè)監(jiān)聽(tīng)端口,與客戶端建立連接之后,生成了一個(gè)新套接字。這時(shí)我執(zhí)行了只關(guān)閉監(jiān)聽(tīng)端口的語(yǔ)句,結(jié)果卻發(fā)現(xiàn)監(jiān)聽(tīng)端口和已建立的連接仍然存在。我都已經(jīng)關(guān)閉了監(jiān)聽(tīng)套接字,為什么客戶端還可以繼續(xù)往監(jiān)聽(tīng)端口發(fā)信息?這到底是因?yàn)槭裁茨??新套接字和監(jiān)聽(tīng)套接字有什么關(guān)系呢? 比如,你開(kāi)了80監(jiān)聽(tīng)端口,有一個(gè)客戶連接你accept了,這時(shí)關(guān)閉80端口。但此時(shí)客戶端發(fā)信息的時(shí)候必然是發(fā)向80斷口,但是80已經(jīng)關(guān)了啊,但是通信依然正常進(jìn)行。其實(shí)我剛接觸套接字的時(shí)候也是認(rèn)為所有從客戶端發(fā)來(lái)的數(shù)據(jù)都需要經(jīng)過(guò)監(jiān)聽(tīng)套接字轉(zhuǎn)一下才能收到。所有的初學(xué)者都容易犯這個(gè)誤解。 經(jīng)過(guò)一段時(shí)間的使用,我現(xiàn)在是明白了,監(jiān)聽(tīng)套接字就是個(gè)牽線指路的,你實(shí)質(zhì)上是跟它指的那個(gè)人說(shuō)話。因?yàn)槟阋业哪莻€(gè)人不可能隨時(shí)等你來(lái),而監(jiān)聽(tīng)套接字就是專職等你來(lái)問(wèn),它回答你要找的人在哪,并喚醒你要找的人,于是通話就建立起來(lái)了,就像現(xiàn)實(shí)生活中的接線員一樣。 也就是說(shuō),在連接建立后,客戶端用發(fā)出連接的那個(gè)SOCKET向服務(wù)器發(fā)數(shù)據(jù),是發(fā)給服務(wù)器新創(chuàng)建的SOCKET,而不是服務(wù)器的監(jiān)聽(tīng)SOCKET。服務(wù)器的監(jiān)聽(tīng)SOCKET永遠(yuǎn)只是用來(lái)接受連接請(qǐng)求。 這就好比你去吃飯,飯館門(mén)口有迎賓小姐(監(jiān)聽(tīng)SOCKET)看到你來(lái)后和你打招呼,然后(ACCEPT)找來(lái)一個(gè)新的服務(wù)員(NEW SOCKET)來(lái)接待你,然后守在門(mén)口繼續(xù)監(jiān)聽(tīng)下一個(gè)。監(jiān)聽(tīng)的小姐走了,接待你的服務(wù)員當(dāng)然不受影響。 說(shuō)到這里有必要說(shuō)一下accept()函數(shù)。以下是《Linux網(wǎng)絡(luò)編程》一書(shū),第六章 Berkeley套接字對(duì)accept()函數(shù)的描述: 函數(shù) accept()有一些難懂。當(dāng)調(diào)用它的時(shí)候,大致過(guò)程是下面這樣的: ● 有人從很遠(yuǎn)很遠(yuǎn)的地方嘗試調(diào)用 connect()來(lái)連接你的機(jī)器上的某個(gè)端口(當(dāng)然是你已經(jīng)在 listen()的)。 ● 他的連接將被 listen 加入等待隊(duì)列等待 accept()函數(shù)的調(diào)用(加入等待隊(duì)列的最多數(shù)目由調(diào)用 listen()函數(shù)的第二個(gè)參數(shù) backlog 來(lái)決定)。 ● 你調(diào)用 accept()函數(shù),告訴他你準(zhǔn)備連接。 ● accept()函數(shù)將回返回一個(gè)新的套接字描述符,這個(gè)描述符就代表了這個(gè)連接! 好,這時(shí)候你有了兩個(gè)套接字描述符,返回給你的那個(gè)就是和遠(yuǎn)程計(jì)算機(jī)的連接,而第一個(gè)套接字描述符仍然在你的機(jī)器上原來(lái)的那個(gè)端口上 listen()。 這時(shí)候你所得到的那個(gè)新的套接字描述符就可以進(jìn)行 send()操作和recv()操作了。 |
|