我制作了简单的套接字程序(服务器/客户端)。 服务器正在Windows上工作,客户端是android应用程序,其中包含由c socket组成的共享库。
在客户端,为了避免冻结我将套接字更改为NON_BLOCK,而不是在传递connect()函数后回滚到BLOCK套接字。之后,我可以使用getpeername()获得搜索连接。
如下......
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags|O_NONBLOCK);
nRet = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
if (nRet < 0)
if (errno != EINPROGRESS && errno != EWOULDBLOCK)
return ERR_CONN;
...
...
nRet = select(sock+1, &readset, &writeset, NULL, &tv);
if (nRet == 0)
if (errno != EINPROGRESS && errno != EWOULDBLOCK)
return ERR_SELECT;
nRet = getpeername(sock, (struct sockaddr*)&addr, &len);
if (nRet != 0)
return ERR_GETPEER;
fcntl(sock, F_SETFL, flags);
一切都运作良好。除了在3G模式下工作。
有时即使Server有连接,客户端也会在getpeername()中返回错误。 错误代码是ENOTCONN。
我应该实施什么来避免这种情况?任何建议都会受到赞赏。 thx提前。
我发现了什么是错的。
首先,我应该在返回之前传递connect()之后回滚到BLOCK套接字。 第二,似乎select()不保证持有timeval,所以我使得像GetTickCount()这样的函数比计算中断循环的时间。
这是我的解决方案。
fcntl(O_NONBLOCK);
connect();
fcntl(BLOCK);
while (true)
{
fd_set rdfs, wdfs;
FD_ZERO(&rdfs); FD_ZERO(&wdfs);
FD_SET(sock, &rdfs); FD_SET(sock, &wdfs);
tv.tv_sec = 0; tv.tv_usec = 100;
nRet = select(sock + 1, &rdfs, &wdfs, NULL, &tv);
if (nRet == -1) return -1;
else if (nRet)
{
nRet = getpeername();
if (!nRet)
break;
}
if (get_tick_count() - delay > timeout)
return -2;
}
THX! sarnold,caf:)
答案 0 :(得分:0)
要确定套接字是否已连接,通常使用getsockopt()
而不是getpeername()
:
int so_error;
socklen_t len = sizeof so_error;
getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error == 0) {
/* socket is connected */
}