ServerSocket Accept 一些理解

當(dāng)我們調(diào)用如下代碼的時(shí)候,實(shí)際java封裝了很多層調(diào)用

圖1

new ServerSocket(9876) 這個(gè)構(gòu)造函數(shù)的內(nèi)部,會(huì)調(diào)用 bind() 以及 listen() 等系統(tǒng)調(diào)用,之后才是 accept(),下面依次講解。

bind(): bind 只是簡單的將套接字和 地址端口聯(lián)系上,調(diào)用bind()之后,netstat 不會(huì)看到任何連接

listen(): listen 表示此套接字 已經(jīng)處于監(jiān)聽狀態(tài)了,外部請求可以打進(jìn)來了。


圖2

可以看到,并沒有運(yùn)行到 accept() ,socket已經(jīng)處于監(jiān)聽狀態(tài)了,那此時(shí)如果外部連接打進(jìn)來會(huì)怎樣呢?我們用瀏覽器模擬http請求。 打開 chrome 輸入 127.0.0.1:9876 回車,


圖3

可以看到 55870 端口建立了連接 (ESTABLISHED 表示連接已經(jīng)建立)? (55868那個(gè)端口不知道怎么來的,有知道的大神希望能指點(diǎn)一下)。然后我們在瀏覽器多開幾個(gè)窗口輸入,會(huì)發(fā)現(xiàn)連接建立的更多了。


圖4

所以,listen的時(shí)候,是可以接收請求并建立連接的,只是不處理這個(gè)socket的內(nèi)容而已。參考UNIX網(wǎng)絡(luò)編程(卷一,套接字聯(lián)網(wǎng)API 第三版 p85),此時(shí)系統(tǒng)維護(hù)兩個(gè)隊(duì)列,未完成建立連接隊(duì)列(三次握手只進(jìn)行了第一步)和 已完成建立連接隊(duì)列(上述ESTABLISTHED的連接)。而之后的 accept() 會(huì)在已建立連接隊(duì)列獲取套接字來處理。

accept() :會(huì)從上述已建立連接套接字隊(duì)列,獲取隊(duì)列頭部的socket,來進(jìn)行處理,每次accept()都會(huì)返回一個(gè)對應(yīng)客戶端的全新socket 。當(dāng)建立連接隊(duì)列為空時(shí),accept會(huì)阻塞并處于睡眠狀態(tài)。

另注:當(dāng)accept() 之后,如果一個(gè)請求打過來,服務(wù)器處理請求之后,并不會(huì)將連接中斷,而是會(huì)一直通過 客戶端的 keepAlived 來維持這個(gè)連接


圖4

可以看到? 都是從客戶端發(fā)送的 keepalived 請求,服務(wù)端回應(yīng)ack。

補(bǔ)充一下:在listen之前,創(chuàng)建的socket都默認(rèn)為要主動(dòng) connect 其他服務(wù)的,即為主動(dòng)socket,只有l(wèi)isten 之后,socket 才變?yōu)楸粍?dòng)的。服務(wù)端的socket 都是listen了之后,才變?yōu)榉?wù)socket的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容