摘要:對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。
accept函式等待並接受客戶請求:
#include
int accept(int sockfd, struct sockaddr* addr, socklen_t* len)
返回:非負描述字——成功, -1——失敗
accept缺省會阻塞程序,直到有乙個客戶連線建立後返回,它返回的是乙個新可用的套接字,這個套接字是連線套接字。此時我們需要區分兩種套接字,一種套接字正如accept的引數sockfd,它是監聽套接字,在呼叫listen函式之後,乙個套接字會從主動連線的套接字變身為乙個監聽套接字;而accept返回是乙個連線套接字,它代表著乙個網路已經存在的點點連線。自然要問的是:為什麼要有兩種套接字?原因很簡單,如果使用乙個描述字的話,那麼它的功能太多,使得使用很不直觀,同時在核心確實產生了乙個這樣的新的描述字。
引數sockfd
引數sockfd就是上面解釋中的監聽套接字,這個套接字用來監聽乙個埠,當有乙個客戶與伺服器連線時,它使用這個乙個埠號,而此時這個埠號正與這個套接字關聯。當然客戶不知道套接字這些細節,它只知道乙個位址和乙個埠號。
引數addr
這是乙個結果引數,它用來接受乙個返回值,這返回值指定客戶端的位址,當然這個位址是通過某個位址結構來描述的,使用者應該知道這乙個什麼樣的位址結構。如果對客戶的位址不感興趣,那麼可以把這個值設定為null。
引數len
如同大家所認為的,它也是結果的引數,用來接受上述addr的結構的大小的,它指明addr結構所占有的位元組個數。同樣的,它也可以被設定為null。
如果accept成功返回,則伺服器與客戶已經正確建立連線了,此時伺服器通過accept返回的套接字來完成與客戶的通訊。
這周同學們在做網路程式設計的時候,碰到乙個監聽套接字的問題,在這裡大概描述一下:
比如我的程式開了乙個監聽埠,與客戶端建立連線之後,生成了乙個新套接字。這時我執行了只關閉監聽埠的語句,結果卻發現監聽埠和已建立的連線仍然存在。我都已經關閉了監聽套接字,為什麼客戶端還可以繼續往監聽埠發資訊?這到底是因為什麼呢?新套接字和監聽套接字有什麼關係呢?
比如,你開了80監聽埠,有乙個客戶連線你accept了,這時關閉80埠。但此時客戶端發資訊的時候必然是發向80斷口,但是80已經關了啊,但是通訊依然正常進行。其實我剛接觸套接字的時候也是認為所有從客戶端發來的資料都需要經過監聽套接字轉一下才能收到。所有的初學者都容易犯這個誤解。
經過一段時間的使用,我現在是明白了,監聽套接字就是個牽線指路的,你實質上是跟它指的那個人說話。因為你要找的那個人不可能隨時等你來,而監聽套接字就是專職等你來問,它回答你要找的人在哪,並喚醒你要找的人,於是通話就建立起來了,就像現實生活中的接線員一樣。
也就是說,在連線建立後,客戶端用發出連線的那個socket向伺服器發資料,是發給伺服器新建立的socket,而不是伺服器的監聽socket。伺服器的監聽socket永遠只是用來接受連線請求。
這就好比你去吃飯,飯館門口有迎賓小姐(監聽socket)看到你來後和你打招呼,然後(accept)找來乙個新的服務員(new socket)來接待你,然後守在門口繼續監聽下乙個。監聽的小姐走了,接待你的服務員當然不受影響。
說到這裡有必要說一下accept()函式。以下是《linux網路程式設計》一書,第六章 berkeley套接字對accept()函式的描述:
函式 accept()有一些難懂。當呼叫它的時候,大致過程是下面這樣的:
● 有人從很遠很遠的地方嘗試呼叫 connect()來連線你的機器上的某個埠(當然是你已經在 listen()的)。
● 他的連線將被 listen 加入等待佇列等待 accept()函式的呼叫(加入等待佇列的最多數目由呼叫 listen()函式的第二個引數 backlog 來決定)。
● 你呼叫 accept()函式,告訴他你準備連線。
● accept()函式將回返回乙個新的套接字描述符,這個描述符就代表了這個連線!
好,這時候你有了兩個套接字描述符,返回給你的那個就是和遠端計算機的連線,而第乙個套接字描述符仍然在你的機器上原來的那個埠上 listen()。
這時候你所得到的那個新的套接字描述符就可以進行 send()操作和recv()操作了。
通過上面的解釋,相信您一定已經對監聽套接字有了進一步的了解了吧!
監聽套接字 連線套接字的區別
摘要 對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。accept函式等待並接受客戶請求 inclu...
TCP如何區分監聽套接字和已連線套接字???
2010 10 09 10 39 868人閱讀收藏 tcp伺服器 wildcard freebsd socket 2010 2.10 tcp埠號與併發伺服器 併發伺服器中主伺服器迴圈通過派生乙個子程序來處理每個新的連線。如果乙個子程序繼續使用伺服器眾所周知的埠來服務乙個長時間的請求,那將發生什麼?讓...
accept中的監聽套接字和已連線套接字
int accept int sockfd,struct sockaddr cliaddr,socklen t addrlen 該函式用於從已完成連線的佇列隊頭返回下乙個已完成連線。其中sockfd為監聽套接字 cliaddr和addrlen由核心填入客戶端的協議位址 返回值為已連線套接字 乙個服務...