2011-11-16 157 views
1

有我做的简单的套接字程序(服务器/客户端)。 服务器正在运行的Windows和客户端是Android应用程序,其中包含由c socket构成的共享库。getpeername无法识别连接建立

在客户端,为了避免冻结,我将套接字更改为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模式下工作。

有时即使服务器得到连接,客户端返回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,咖啡馆:)

+0

没有你的'选择(2)'实际上返回'sock'在' readset'?你的意思是 – sarnold

+0

,我查了FD_ISSET吗?对不起,我的可怜的英语:(如果是这样,不,不,我没有检查FD_ISSET getpeername之前 – JayMuzie

+0

是的,就是这样;你应该只尝试读出类似于'FD_ISSET(3 )'为你的'readset'输出变量。 – sarnold

回答

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