シンプルなソケットプログラム(サーバー/クライアント)があります。 サーバはWindows上で動作しており、クライアントはcソケットで作られた共有ライブラリを含むAndroidアプリです。getpeernameは確立された接続を認識できません。
クライアント側で、フリーズしないようにしました。connect()関数を渡した後、BLOCKソケットへのロールバックよりもソケットをNON_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をチェックしましたか? – JayMuzie
はい、それは正確です; 'FD_ISSET(3)に表示されているソケットでは、読み込みのような操作を試みるべきです。(FD_ISSETの前にFD_ISSETをチェックしていませんでした。 ) 'をあなたの' readset'出力変数に置き換えます。 – sarnold