getpeername无法识别已建立的连接

时间:2011-11-16 01:44:46

标签: android c

我制作了简单的套接字程序(服务器/客户端)。 服务器正在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:)

1 个答案:

答案 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 */
}