怎樣簡單檢測socket的健康狀態

2021-06-19 07:44:19 字數 1814 閱讀 5518

載自:

開發程式經常用到socket,新手熟手一般都會用select、recv和send這樣幾個函式,而且大多數情況下,會用這幾個函式也就差不多了。更深入的開發會發現,現成的socket函式並沒有提供檢測socket是否健康的函式,通常的資料也並沒有現成的方法可用。本文提供了乙個方案,在windows和linux下初步測試,效果良好。

必須先宣告的是socket通訊是雙工的(如果讀者對此不了解,可先查一下相關資料)。因此socket的健康狀態是分兩個方向的,乙個是你傳送(send)的方向,乙個是你接收(recv)方向的。只有兩個方向都是關閉的,這個socket才是真正關閉的,也只有這兩個方向都是健康的,此socket才是真正健康的。真正難以檢測的,其實就是這種半健康狀態的socket。當然我們也可以認為,如果我們兩個方向的狀態都可以檢測清楚,那麼此socket的健康狀態我們自然就清楚了。

好了,先認識一下上面提到的三個函式返回值的含義。

函式名

返回值

select

0 :超時

-1 :socket出錯

>0 :有資料已到達

send

0 :傳送緩衝區已滿

-1 :socket出錯

>0 :本次已傳送到緩衝區的位元組數

recv

0 :對方已主動關閉了此socket

-1 :socket出錯

>0 :本次已成功接收的位元組數

應該說,你傳送(send)方向的健康是由你來控制的,只要你不主動呼叫close或closesocket,它就是健康的。如果你關閉了這個方向的socket,原則上你一定能記得住,如果實在記不住,getsockname/ getpeername可以幫你檢測其狀態,它們會返回此socket在本機的ip位址和埠號,如果它們返回-1,那就是你已經主動關閉了這個socket的傳送(send)方向。

麻煩在另一端主動關閉了他的傳送(send)方向,而這在你看來是你的接收(recv)方向被關閉了。另一端的這個關閉動作理論上是可以隨時發生的,不需要事前通知,也沒法事後通知,因此只能由你這一方想辦法檢測。

簡單地說,當你的接收(recv)方被關閉後,你的select會返回》0的值(這說明對方有資料傳送過來),你的recv會返回0(這說明對方已經主動關閉了你的接收recv方向)。這兩個值聯合起來,說明對方在主動斷開後,確實向你這一方傳送了資料,但不幸的是,你一接卻是個0位元組大小。有關socket的幾種狀態的資料,網上很多,大家可以自己去查。

上面的方法在通常的實踐中就可以使用了,但如果你就想檢測socket的接收(recv)方向的狀態,就還需要另乙個技巧。recv一般是會從緩衝區中拿走資料的,所以當你只想檢測狀態而又不想拿走資料時,得學會使用recv的第四個引數的用法。通常情況下它是0,但當它為msg_peek時,它的意思是偷看,即看一下緩衝區前面的若干位元組,但並不從緩衝區中拿走。在本方案中,只要偷看1個位元組就好了,如果返回0,就說明對方已經主動發起關閉了。

我們來總結一下簡單地檢測socket健康狀態的全過程。

1、用getsockname/ getpeername來檢測你的傳送(send)方向的狀態,如果你不知道你是否主動關閉了這個方向;

2、用select和recv(,,1,msg_peek)來共同檢測你的接收(recv)方向的狀態。

特別說明的是,socket的狀態其實分好幾種,如果你需要詳細了解它們的獲取方式,歡迎你與我一起**。

Socket的簡單認識

socket又稱 套接字 網路上的兩個程式通過乙個 雙向的通訊連線實現資料的交換 這個連線的一端稱為乙個 socket。應用程式通常通過 套接字 向網路發出請求或者應答網路請求 網路通訊的要素 網路上的請求就是通過 socket 來建立連線然後互相通訊 ip位址 網路上主機裝置的 唯一標識 埠號 定...

簡單的socket程式設計

服務端tcp server.c include include include include include include include define port 8888 埠位址 define backlog 2 監聽佇列長度 int main int argc,char argv memse...

簡單的Socket示例

命令列引數 server.exe portnumber,例如server 8000 client.exe ipaddress portnumber,例如client 127.0.0.1 8000 然後在客戶端的命令列輸入字串並回車,客戶端將會把訊息傳送到伺服器。伺服器再把訊息傳回客戶端。伺服器端,s...