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,咖啡館:)
沒有你的'選擇(2)'實際上返回'sock'在' readset'?你的意思是 – sarnold
,我查了FD_ISSET嗎?對不起,我的可憐的英語:(如果是這樣,不,不,我沒有檢查FD_ISSET getpeername之前 – JayMuzie
是的,就是這樣;你應該只嘗試讀出類似於'FD_ISSET(3 )'爲你的'readset'輸出變量。 – sarnold