首页
社区
课程
招聘
关于TCP连接中使用KeepAlive来判断网络是否断开的问题
发表于: 2009-1-16 20:57 6587

关于TCP连接中使用KeepAlive来判断网络是否断开的问题

2009-1-16 20:57
6587
今天怎么也搞不明白心跳机制判断网络是否断开,网上没找不到相应的代码,只好写了下面的这个,
但是问题又来了,每当到代码中红色的那里就再也不动了,不知道为什么?
我想要的结果是:
客户端就是直接连接服务端,然后一个recv(),由于下面的代码没有send()所以客户端一直等待,这时我把客户端关掉,叫下面的代码显示用户已经断线.
要想得到说的效果该怎么改?
问题代码:
#include <stdio.h>
#include <WinSock2.h>
#pragma comment( lib, "ws2_32.lib" )
typedef struct tcp_keepalive {
 u_long  onoff;
 u_long  keepalivetime;
 u_long  keepaliveinterval;
}tcp_keepalive,*ptcp_keepalive;
#define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
 
void main()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD( 1, 1 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
 {
  return;
 }
 if ( LOBYTE( wsaData.wVersion ) != 1 ||
  HIBYTE( wsaData.wVersion ) != 1)
 {
  WSACleanup();
  return; 
 }
 SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr =htonl(INADDR_ANY);
 addrSrv.sin_family =AF_INET;
 addrSrv.sin_port =htons(6000);
 bind(sockSrv,(sockaddr*)&addrSrv,sizeof(SOCKADDR));
 
 listen(sockSrv,SOMAXCONN);
 
 SOCKADDR_IN addrClient;
 int len=sizeof(SOCKADDR);
 SOCKET sockconn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
 tcp_keepalive InKeepAlive; //, OutKeepAlive;
 const char chOpt = 1;
 DWORD dw;
 HANDLE hCompletionPort = CreateIoCompletionPort( (HANDLE)sockconn, NULL, 0, 0 );
 int iRet = setsockopt(sockconn,SOL_SOCKET,SO_KEEPALIVE,(char *)&chOpt,sizeof(int));
 if ( iRet == SOCKET_ERROR )
 {
  printf( "Error Setting!\n" );
 
 }
 InKeepAlive.onoff = 1;
 InKeepAlive.keepalivetime = 3000;
 InKeepAlive.keepaliveinterval = 1;
 
 if ( WSAIoctl( sockconn, SIO_KEEPALIVE_VALS, (LPVOID)&InKeepAlive, sizeof( tcp_keepalive ), \
  NULL, 0, &dw, NULL, NULL ) == SOCKET_ERROR )
 {
  printf( "WSAIoctl Error!\n" );
  closesocket(sockconn);
  return;
 }
 char buff[100];
 sprintf(buff,"Welcome %s to here",inet_ntoa(addrClient.sin_addr ));
 printf( "%s\n", buff );
 while(1)
 {
 
  BOOL bRet = FALSE;
  DWORD dwTrans = 0;
  DWORD dwKey = 0;
  LPOVERLAPPED lpOverlapped;
  [COLOR=red]bRet = GetQueuedCompletionStatus( hCompletionPort, &dwTrans, &dwKey, &lpOverlapped,  INFINITE );[/COLOR]
  if ( bRet == FALSE )
  {
   //对方已经断线
   printf( "对方已经断线\n" );
   closesocket(sockconn);
   return;
  }
 }
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 296
活跃值: (20)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
1 尽量不要用keepalive,不准确或者不好试.而且默认是2个小时.

2 使用心跳机制判断是否在线.因为client端由于网络设备,或者计算机crush,不会通知服务器socket已经关闭.

3 GetQueuedCompletionStatus: 这是完成断口. 你都没有做任何recv或者send操作,不知道要等待什么? 等待的问题是流程有问题.
2009-1-17 20:41
0
游客
登录 | 注册 方可回帖
返回
//