我們在編寫socket客戶端程式時,必須要提前考慮 伺服器異常 時的應對措施,伺服器的動作主要有3種:
(1)伺服器正常,返回給客戶端正常資料,也就是正常的資料業務,那麼客戶端的套接字變為可讀,並且read返回乙個大於0的值(即讀入資料的位元組數)。
(2)伺服器正常終止,給客戶端傳送fin,那麼客戶端的套接字變為可讀,並且read返回0(eof)。
(3)伺服器崩潰,包括崩潰後重啟,會給客戶端傳送rst,那麼客戶端的套接字變為可讀,並且read返回-1,而errno中包含了確切的錯誤碼。
這裡要特別注意:(2、3)兩種異常情況下,會導致套接字可讀,而且是一直可讀,而(1)中雖然也可讀,但是讀完以後,就不可讀了。這就意味著我們在使用select時,(2)、(3)情況下,select會一直返回的,所以需要做一些避免方式。
我們來舉乙個實際的工程案例,開發乙個 串列埠轉乙太網模組,實現modbus rtu→modbus tcp的轉換,這個應用中,我們的裝置的tcp,相當於 客戶端 client,一旦連線到 tcp server 後,就可以實現雙向傳輸了,但是這個裡面有個實際情況,一般服務端在accept乙個新的client後,會 做計時,如果在某個時間段內,沒有資料互動,伺服器會關閉 這個 server 子程序,那麼就會向 我們的模組 傳送 fin,這個時候,我們的模組肯定要做預案處理的,我們先看一下沒有做預案處理的**(不嚴謹的**):
/* 客戶端socket初始化*/
/* 串列埠初始化,開啟*/
connect(socketfd,....)
/* fd_set 初始化*/
while( 1 )
if(fd_isset(usart1fd, &read_set))
else printf("usart rx error!\n");
}if(fd_isset(socketfd, &read_set))
else printf("socket rx error!\n");;}}
這段**,在伺服器正常情況下,是能用的,可以 實現串列埠資料 轉 tcp資料,但是如果伺服器出現上面的(2)、(3)異常時,由於socketfd變成一直可讀,所以會一直迴圈列印輸出 "socket rx error!"
解決辦法:
(1)可以嘗試重新連線伺服器,不過前面說過 connect 是不能直接重啟的,我們需要重新 呼叫socket 初始化,然後再連線。
(2)exit 退出。
另外:如果伺服器有連線時間要求,即間隔多久 時間後,必須有資料業務,否則就關閉服務 子程序,那麼我們可以傳送 「心跳」、設定socket 引數選項為 so_keepalive,等。
Socket程式設計獲取伺服器時間
客戶端向伺服器端傳送請求,伺服器收到請求做相應的處理,將處理結果傳回客戶端。下面採用tcp協議實現伺服器和客戶端之間的連線。1.客戶端 約定雙方的傳輸協議 udp或者tcp 根據傳輸協議建立socket 伺服器的ip位址和埠號 連線伺服器 獲取伺服器傳遞回來的資料。cpp include inclu...
socket程式設計 10 實現迭代伺服器端和客戶端
前面的程式,不管伺服器端還是客戶端,都有乙個問題,就是處理完乙個請求立即退出了,沒有太大的實際意義。能不能像web伺服器那樣一直接受客戶端的請求呢?能,使用 while 迴圈即可。修改前面的回聲程式,使伺服器端可以不斷響應客戶端的請求。伺服器端 server.cpp include include ...
socket多執行緒通訊(乙個伺服器對多個客戶端)
1.伺服器端 include include include include include include include include define port 8888 define max num client 10 struct pthread data void server handl...