クライアント ソケット プログラムをネイティブ コードで記述し、Android アプリケーションで使用しています。サーバーが利用できないときにサーバーに接続するときに、1 つの奇妙な問題に直面しています。
サーバーが利用できない場合、クライアント側の connect() 呼び出しはトスになり、まったく出てきません。これについてネットで調べてみました。いくつかのリンクはこれらの手順を説明していました
- ソケットを非ブロックモードに設定
- 接続の呼び出し - 接続が成功した場合
- それ以外の場合は、ソケットをブロック モードに戻します。
- 書き込みセット用のソケットを設定し、必要なタイムアウトで select() に渡します。
- ソケットが書き込みセットに設定された状態で選択が出た場合、接続は成功するか、接続は失敗します。
これらの手順を試しましたが、サーバーが実行されているかどうかに関係なく、select() 呼び出しは常にタイムアウトのみで発生します。この問題を解決するにはあなたの助けが必要です。
これが私が使用しているコードの一部です
bool SocketConnect()
{
... Creating the socket ....
int opts;
if( (opts = fcntl(clientsocket,F_GETFL) < 0 )
{
return false;
}
// setting socket to non-block mode
if( fcntl(clientsocket,opts | O_NONBLOCK) < 0 )
{
return false;
}
//calling connect
int ret = connect(clientsocket,(const sockaddr*)&serveraddr,sizeof(serveraddr));
if( ret < 0 )
{
if( errno != EINPROGRESS )
{
return false;
}
}
if( ret == 0 )
{
//connection successful set the socket to block mode
fcntl(clientsocket,F_SETFL,opts);
return true;
}
//set the socket to block mode
if( fcntl(clientsocket,F_SETFL,opts) < 0 )
{
return false;
}
fd_set writeset;
FD_ZERO(&writeset);
FD_SET(clientsocket,&writeset);
timeval val.
val.tv_sec = 5;
val.tv_usec = 0;
int sret = select(clientsocket+1,NULL,&writeset,NULL,&val);
if( sret > 0 )
{
if( FD_ISSET(clientsocket,&writeset) )
{
fcntl(clientsocket,F_SETFL,opts);
return true;
}
}
return false;
}
ブロックされた接続呼び出しを使用すると(上記の手順を使用せずに)サーバーが使用可能な場合、接続を確立するのに1秒もかかりません。
上記の手順を使用して接続を行うとサーバーが利用可能になり、接続が確立されない5秒の時間を与えるとイベントが発生します。イベント選択も5秒待たず、すぐに出て値0を返しました。
このコードを確認して、connection() 呼び出しのタイムアウトを設定する際にどこが間違っているのか教えてください..
達成するための提案や代替方法は大歓迎です。
ありがとうございました。