小妹急问:PC做服务器,接多台ARM嵌入式,怎么及时的判断连接台数?

青松2 2013-10-18 06:20:20
一个C/S项目,是基于ARM的多台嵌入式系统连接PC,PC做服务器接收多台ARM的数据。我用的是WSAAsyncSelect模式。现在的情况是:连接、接收数据都没有问题,但是如果有一台ARM中间断开后,PC要过大概30秒才能判断连接断开。

我之前在VC中,用WSAAsyncSelect注册FD_ACCEPT 、FD_CLOSE消息来判断连接的台数,但是发现很多时候连接断开后并没有收到FD_CLOSE消息!现在我用给每台客户端发送心跳包的形式来检测连接台数,也就是每隔一秒给每个SOCKET发送心跳数据,如果发送成功,表明连接正常,如果发送不出,则表明连接断开。如下:
n=send(p-> m_clients[i], (char*)comcode, 6, 0);
根据n的返回值来判断是否发送成功。

现在的问题是:这样判断,总体结果是正确的,也就是说如果有断开时,过30秒后显示的连接台数才是正确的!这显然无法让人接受!

请问各位怎么让其中一台客户端网络断开时,VC立即就知道断开了?



...全文
11304 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
青松2 2013-10-22
  • 打赏
  • 举报
回复
引用 18 楼 VisualEleven 的回复:
你把心跳间隔时间设置短一点不行吗?
心跳间隔0.1秒还是0.3秒,反应时间都在20秒以上啊。。。崩溃。。。
青松2 2013-10-22
  • 打赏
  • 举报
回复
引用 17 楼 dcmilan 的回复:
你不就是想知道在线的装置数么? 装置侧的通信规约你有么? 你就定期的问一个发一个数据然后看echo 如果没有返回数据说明这台装置离线了 我们做电力监控的时候基本都用这种方法判断
谢谢大哥回复,能够指教具体一点?您说的我不懂啊,更不知道具体怎么做。。
Eleven 2013-10-22
  • 打赏
  • 举报
回复
你把心跳间隔时间设置短一点不行吗?
RabinSong 2013-10-22
  • 打赏
  • 举报
回复
检测是否掉线的线程的实现如下: 发送心跳包的线程:(每1秒发送1次) while(1) { sendHeartPkg();//收到信号包的下位机应答该心跳包,(该心跳包最好广播发送) sleep(1000); } 检查是否掉线的线程: while(1) { checkOffline();//检查是否有应答(如3次检查都没有应答,则表示设备掉线,前提设备如果没有掉线,3秒内必定有应答) sleep(1000); } 这种方式3秒内就可以检测出设备是否掉线,看你的需要来改变检测时间 当然了你也可以用定时器实现,检测和发送心跳包可以放同一个线程
  • 打赏
  • 举报
回复
你不就是想知道在线的装置数么? 装置侧的通信规约你有么? 你就定期的问一个发一个数据然后看echo 如果没有返回数据说明这台装置离线了 我们做电力监控的时候基本都用这种方法判断
昆仑道长 2013-10-21
  • 打赏
  • 举报
回复
妹子,我会帮你祷告的,祝你平安~
引用 15 楼 lhfslhfs 的回复:
啊啊啊啊啊啊啊啊啊啊,还是解决不了,有大哥哥帮我吗?
青松2 2013-10-21
  • 打赏
  • 举报
回复
啊啊啊啊啊啊啊啊啊啊,还是解决不了,有大哥哥帮我吗?
worldy 2013-10-19
  • 打赏
  • 举报
回复
为什么要30s才能反应断开?你的超时时间设置太长了,如果是这样,改超时时间,另外,端口断开之前,如果是正常端口可以发送一个终止消息给主机
青松2 2013-10-19
  • 打赏
  • 举报
回复
这个方法根本不行啊!
引用 2 楼 shb8845369 的回复:
亲爱的菇凉,惦记你的人又来啦~~,以下文章来自CodeProject,是否中意呢?

/*Sometimes, the connect time-out can take too much time when the target is unavailable. To resolve this issue, we can use non-blocking socket mode to select
the timeout. */
bool connect(char *host,int port, int timeout)
{
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    struct sockaddr_in address;  /* the libc network address data structure */   
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    address.sin_addr.s_addr = inet_addr(host); /* assign the address */
    address.sin_port = htons(port);            /* translate int2port num */	
    address.sin_family = AF_INET;
 
    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
	    
    if(connect(sock,(struct sockaddr *)&address,sizeof(address))==false)
    {	
        return false;
    }	
 
    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
 
    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(sock, &Write);
    FD_SET(sock, &Err);
 
    // check if the socket is ready
    select(0,NULL,&Write,&Err,&Timeout);			
    if(FD_ISSET(sock, &Write)) 
    {	
        return true;
    }
 
    return false;
}
斗胆问一句: 姑娘年方几何? 有无情郎?
昆仑道长 2013-10-19
  • 打赏
  • 举报
回复
下面是前人总结的所有方法,你先试试看,哪个好用。 1、Add a keepalive message to the application protocol framing (an empty message). 2、Add a keepalive message to the actual application protocol (a "null" message). 3、Explicit timer assuming the worst. 4、Manipulate the TCP/IP keepalive packet settings. 翻译如下: 1. 间隔一段时间,发送TCP KeepAlive数据包,无任何数据,判断返回值。客户端程序无需改动 2. 间隔一段时间,发送TCP KeepAlive数据包,加一个null标志位,客户端程序需要改动,如果客户端还是alive的话,数据直接丢弃,然后返回一个应答给服务器端. 3. 史上最愚蠢的方法,在规定的间隔内,没有收到应答数据包就认为连接不可用,容易误报,但值得一试。 4. 一个折衷的方案,手动设置TCP KeepAlive包设置,对windows有版本要求。 原文链接:http://www.codeproject.com/Articles/37490/Detection-of-Half-Open-Dropped-TCP-IP-Socket-Conne 此外,按常理,你的界面应该也是在1~2秒之内进行一次局部刷新,而不是等所有连接判断完后再全部刷新。如果你采用的是后面这种方法,延时大也是有可能的哦~~~
引用 9 楼 lhfslhfs 的回复:
这个方法根本不行啊! [quote=引用 2 楼 shb8845369 的回复:] 亲爱的菇凉,惦记你的人又来啦~~,以下文章来自CodeProject,是否中意呢?

/*Sometimes, the connect time-out can take too much time when the target is unavailable. To resolve this issue, we can use non-blocking socket mode to select
the timeout. */
bool connect(char *host,int port, int timeout)
{
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    struct sockaddr_in address;  /* the libc network address data structure */   
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    address.sin_addr.s_addr = inet_addr(host); /* assign the address */
    address.sin_port = htons(port);            /* translate int2port num */	
    address.sin_family = AF_INET;
 
    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
	    
    if(connect(sock,(struct sockaddr *)&address,sizeof(address))==false)
    {	
        return false;
    }	
 
    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
 
    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(sock, &Write);
    FD_SET(sock, &Err);
 
    // check if the socket is ready
    select(0,NULL,&Write,&Err,&Timeout);			
    if(FD_ISSET(sock, &Write)) 
    {	
        return true;
    }
 
    return false;
}
斗胆问一句: 姑娘年方几何? 有无情郎?
[/quote]
china_jeffery 2013-10-19
  • 打赏
  • 举报
回复
妹子提问就有这么多大牛回答,我也要去搞个马甲
oyljerry 2013-10-19
  • 打赏
  • 举报
回复
单独线程维持心跳包机制,断开了,就知道那个客户端
向立天 2013-10-19
  • 打赏
  • 举报
回复
你的通信架构有问题吧 怎么可能需要30秒才能知道断开 另外 你不是1秒钟意检测心跳么 这也需要30秒才有结果?
shuihan20e 2013-10-18
  • 打赏
  • 举报
回复
你用的是select 模式,另外,你还可以用一个线程来判断
青松2 2013-10-18
  • 打赏
  • 举报
回复
谢谢哥哥,我明天去测试一下,哥哥真好
引用 4 楼 shb8845369 的回复:
host是连接的客户端IP地址,port是客户端的端口,timeout是超时设置,如果timeout时间内客户端依旧无法找到,服务端就断开连接。这是我的理解,原文在这里,请移芳步~ http://www.codeproject.com/Tips/168704/How-to-set-a-socket-connection-timeout [quote=引用 3 楼 lhfslhfs 的回复:] 嘿嘿,哥哥您先给解释这个函数的参数,以及怎么使用吗?我看不太明白啊哥哥 [quote=引用 2 楼 shb8845369 的回复:] 亲爱的菇凉,惦记你的人又来啦~~,以下文章来自CodeProject,是否中意呢?

/*Sometimes, the connect time-out can take too much time when the target is unavailable. To resolve this issue, we can use non-blocking socket mode to select
the timeout. */
bool connect(char *host,int port, int timeout)
{
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    struct sockaddr_in address;  /* the libc network address data structure */   
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    address.sin_addr.s_addr = inet_addr(host); /* assign the address */
    address.sin_port = htons(port);            /* translate int2port num */	
    address.sin_family = AF_INET;
 
    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
	    
    if(connect(sock,(struct sockaddr *)&address,sizeof(address))==false)
    {	
        return false;
    }	
 
    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
 
    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(sock, &Write);
    FD_SET(sock, &Err);
 
    // check if the socket is ready
    select(0,NULL,&Write,&Err,&Timeout);			
    if(FD_ISSET(sock, &Write)) 
    {	
        return true;
    }
 
    return false;
}
斗胆问一句: 姑娘年方几何? 有无情郎?
[/quote][/quote]
昆仑道长 2013-10-18
  • 打赏
  • 举报
回复
引用 5 楼 sunnyloves 的回复:
就知道csdn的狼都来了
我必须承认,楼上的话一语双关~
洗洗睡去 2013-10-18
  • 打赏
  • 举报
回复
就知道csdn的狼都来了
昆仑道长 2013-10-18
  • 打赏
  • 举报
回复
host是连接的客户端IP地址,port是客户端的端口,timeout是超时设置,如果timeout时间内客户端依旧无法找到,服务端就断开连接。这是我的理解,原文在这里,请移芳步~ http://www.codeproject.com/Tips/168704/How-to-set-a-socket-connection-timeout
引用 3 楼 lhfslhfs 的回复:
嘿嘿,哥哥您先给解释这个函数的参数,以及怎么使用吗?我看不太明白啊哥哥 [quote=引用 2 楼 shb8845369 的回复:] 亲爱的菇凉,惦记你的人又来啦~~,以下文章来自CodeProject,是否中意呢?

/*Sometimes, the connect time-out can take too much time when the target is unavailable. To resolve this issue, we can use non-blocking socket mode to select
the timeout. */
bool connect(char *host,int port, int timeout)
{
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    struct sockaddr_in address;  /* the libc network address data structure */   
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    address.sin_addr.s_addr = inet_addr(host); /* assign the address */
    address.sin_port = htons(port);            /* translate int2port num */	
    address.sin_family = AF_INET;
 
    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
	    
    if(connect(sock,(struct sockaddr *)&address,sizeof(address))==false)
    {	
        return false;
    }	
 
    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
 
    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(sock, &Write);
    FD_SET(sock, &Err);
 
    // check if the socket is ready
    select(0,NULL,&Write,&Err,&Timeout);			
    if(FD_ISSET(sock, &Write)) 
    {	
        return true;
    }
 
    return false;
}
斗胆问一句: 姑娘年方几何? 有无情郎?
[/quote]
青松2 2013-10-18
  • 打赏
  • 举报
回复
嘿嘿,哥哥您先给解释这个函数的参数,以及怎么使用吗?我看不太明白啊哥哥
引用 2 楼 shb8845369 的回复:
亲爱的菇凉,惦记你的人又来啦~~,以下文章来自CodeProject,是否中意呢?

/*Sometimes, the connect time-out can take too much time when the target is unavailable. To resolve this issue, we can use non-blocking socket mode to select
the timeout. */
bool connect(char *host,int port, int timeout)
{
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    struct sockaddr_in address;  /* the libc network address data structure */   
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    address.sin_addr.s_addr = inet_addr(host); /* assign the address */
    address.sin_port = htons(port);            /* translate int2port num */	
    address.sin_family = AF_INET;
 
    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
	    
    if(connect(sock,(struct sockaddr *)&address,sizeof(address))==false)
    {	
        return false;
    }	
 
    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
 
    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(sock, &Write);
    FD_SET(sock, &Err);
 
    // check if the socket is ready
    select(0,NULL,&Write,&Err,&Timeout);			
    if(FD_ISSET(sock, &Write)) 
    {	
        return true;
    }
 
    return false;
}
斗胆问一句: 姑娘年方几何? 有无情郎?
昆仑道长 2013-10-18
  • 打赏
  • 举报
回复
亲爱的菇凉,惦记你的人又来啦~~,以下文章来自CodeProject,是否中意呢?

/*Sometimes, the connect time-out can take too much time when the target is unavailable. To resolve this issue, we can use non-blocking socket mode to select
the timeout. */
bool connect(char *host,int port, int timeout)
{
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    struct sockaddr_in address;  /* the libc network address data structure */   
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    address.sin_addr.s_addr = inet_addr(host); /* assign the address */
    address.sin_port = htons(port);            /* translate int2port num */	
    address.sin_family = AF_INET;
 
    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
	    
    if(connect(sock,(struct sockaddr *)&address,sizeof(address))==false)
    {	
        return false;
    }	
 
    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(sock, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {	
        printf("ioctlsocket failed with error: %ld\n", iResult);
    }
 
    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(sock, &Write);
    FD_SET(sock, &Err);
 
    // check if the socket is ready
    select(0,NULL,&Write,&Err,&Timeout);			
    if(FD_ISSET(sock, &Write)) 
    {	
        return true;
    }
 
    return false;
}
斗胆问一句: 姑娘年方几何? 有无情郎?
加载更多回复(1)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧