轉自 http://blog.csdn.net/loadstar_kun/article/details/5790407
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 DAU success.");
}
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 DAU success.");
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;
}
}