如何判斷SOCKET還是連線著的
1. 用read函式來判斷
讀到長度0不能斷定是已經斷開.除非是-1,才代表輸入流已經被關閉,說名socket已經close,而且關鍵在於你怎麼讀,實際上應該是一個單獨的執行緒一直在讀,因為你無法預先知道能不能一次將發過來的包讀完,也無法知道一次是不是讀完整了包,所以線稱一直迴圈在讀並且一直在解包.這樣即能知道什麼時候server斷,也完成了訊息的解讀,我的方案是這樣的,在大資料量高速率網路上執行沒有發生過丟包
// 判斷是否連線
char ch = 'A';
if (read(g_sockfd, &ch, 1)<=0)
{
if (connect(g_sockfd,(struct sockaddr*)&g_serv_addr, sizeof(g_serv_addr) ) == 0)
{
ServiceLog.write_log("[NotifyDAU]:connect to DAUsuccess.");
}
else
{
ServiceLog.write_log("[NotifyDAU]:can't connect to DAU ");
return;
}
}
用try{}catch{}是比較合適。
當他是連著的,當進行通訊時發生異常後就知道了.
當你不斷的read的時候,server斷,exception就catch到了。
2. 心跳包
可不可以在Client設一個定時器,每隔一段時間發一條訊息給伺服器,看能不能收到伺服器的響應。
心跳包就是定時發包,沒回應就判斷斷開。
3. getsockopt
int optval, optlen = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR,(char*) &optval, &optlen);
switch(optval){
case 0:
//“處於連線狀態“
break;
case ECONNREFUSED:
case EHOSTNUMREACH:
}
4. 專案中使用的情況
// 判斷是否連線
int optval, optlen = sizeof(int);
int r = getsockopt(g_sockfd, SOL_SOCKET, SO_ERROR,(char*) &optval, &optlen);
// send HELLO 包
if ((optval == 0) && (r == 0) && (send(g_sockfd,(char*)&g_DAUCommand,sizeof(struct _DAUCommand),0) != SOCKET_ERROR ))
{
ServiceLog.write_log("[threadOperationWaitTrasferAgain]: try to recv from dau...");
length = recv(g_sockfd,(char *)&command,sizeof(struct _DAUCommand),0);
}
else
{
if (connect(g_sockfd,(struct sockaddr*)&g_serv_addr, sizeof(g_serv_addr) ) == 0)
{
ServiceLog.write_log("[threadOperationWaitTrasferAgain]:connect to DAUsuccess.");
ServiceLog.write_log("[threadOperationWaitTrasferAgain]: try to recv from dau...");
length = recv(g_sockfd,(char *)&command,sizeof(struct _DAUCommand),0);
}
else
{
ServiceLog.write_log("[threadOperationWaitTransferAgain]:can't connect to DAU, try again ");
length = 0;
continue;
}
}