connect()函数阻塞

来源:互联网 发布:mac 拷贝隐藏文件 编辑:程序博客网 时间:2024/05/21 19:33

在XX板的C6678上运行SYS/BIOS操作系统和NDK协议栈。应用层有一个TCP客户端去连接PC上的服务器,然后通过这个连接互发心跳。

    //初始化套接字(TCP)    sockConnect= socket(AF_INET,SOCK_STREAM,0);    //本端地址配置    bzero(&localAddr,sizeof(struct sockaddr_in));    localAddr.sin_family = AF_INET;    localAddr.sin_len = sizeof(struct sockaddr_in);    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);    localAddr.sin_port = connectLocalPort;    // 绑定本端端口    ret32 = bind(sockConnect,(SA*)&localAddr,sizeof(localAddr));    //对端地址配置    bzero(&remoteAddr,sizeof(struct sockaddr_in));    remoteAddr.sin_family = AF_INET;    remoteAddr.sin_len = sizeof(struct sockaddr_in);    remoteAddr.sin_addr.s_addr = connectRemoteIP;    remoteAddr.sin_port = connectRemotePort;    //连接服务器    M_DEBUG(DBG_LEVEL_WARNING,"connect server ...\n");    ret32 = connect(sockConnect,(struct sockaddr*)&remoteAddr,sizeof(remoteAddr));    if (ret32<0)    {        fdClose(sockConnect);        return RET_ERR;    }    //通过该连接发送心跳    ...

在远程机房调试,XX板通过一台交换机连接一个WinXP机作为服务器端A,另一台交换机连接另一个Win7机作为备份服务器端B。当使用A时代码运行正常,然而切换到B环境后发现心跳消失了。

一开始怀疑是备份切换机制出了问题,将问题版本带回实验室后却无法复现,即切换到实验室的备份机上仍能正常工作。这时开始怀疑是环境出了问题。比较两个环境,IP配置完全一致,区别一是远端B和实验室B的交换机品牌不同,二是实验室B的服务器使用的是WinXP。

再分析远端抓包,发现connect调用后向服务器发送SYN握手,但对端未回响应。在实验室版本上的SYN握手收到RST回复。

这里就出现了两个问题,一是为什么正常版本会有RST,二是不正常版本为什么没有RST。

第一个问题很快查出来了,是因为手误配错了端口号导致服务器回RST,这使得connect函数返回错误,启动的另一套错误处理机制起作用,开启了心跳。而如果没有RST则connect会一直阻塞不返回,后面当然不会执行到心跳代码。

开始解决第二个问题,RST上哪了?一开始以为是被交换机吞了,换用另一个品牌的交换机仍然没有。在作为服务器的AB机上同时开启抓包软件,结果发现两者都收到了SYN,WinXP回复RST,但Win7却什么都没回。

真相大白,RFC中对这个行为并没有作出明确规定,只是称服务器”may”发送RST,言下之意当然也可以”may not”。而不同的Windows版本的协议栈会有不同的行为,才导致了有时候会出问题有时候没问题。

解决问题还是要从根上想办法。connect是个阻塞函数,就不能让它一直阻塞下去,而是要设置一个超时时间。NDK的默认超时时间是80s,超过了本应用的心跳超时时间。可以配置为更短的值来更早发现问题。修改后问题解决。

0 0
原创粉丝点击