現在、tcp 接続を開くメソッドにタイムアウトを追加しようとしています。選択の代わりに使用しようとしていることを除いて、ここにあるガイドを大まかに使用しています。ただし、接続が開いていなくても、fdの書き込み準備ができていることを通知するpoll()
呼び出しがすぐに返されます。poll()
これは、私が作成した縮小コードの例です。
#include <cstring>
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <cerrno>
#include <iostream>
#include <cstdlib>
int main() {
struct addrinfo hints;
::memset( &hints, 0, sizeof( hints ) );
hints.ai_socktype = 0;
hints.ai_family = AF_UNSPEC;
hints.ai_protocol = 0;
hints.ai_flags = AI_CANONNAME;
struct addrinfo * info;
if( ::getaddrinfo( "127.0.0.1", "49999", &hints, &info ) != 0 ) {
std::cerr << "Error: getaddrinfo" << std::endl;
exit( 1 );
}
int soc;
if( (soc = ::socket( info->ai_family, info->ai_socktype, info->ai_protocol ) ) < 0 ) {
std::cerr << "Erorr: socket" << std::endl;
}
// Set mode to non-blocking for timeout handling
int arg;
if( (arg = ::fcntl( soc, F_GETFL, 0 )) < 0 ) {
std::cerr << "Error: fcntl" << std::endl;
exit( 1 );
}
arg |= O_NONBLOCK;
if( ::fcntl(soc, F_SETFL, arg) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit( 1 );
}
int res = ::connect(soc,info->ai_addr,info->ai_addrlen);
if( (res != 0) && (errno != EINPROGRESS) ) {
std::cerr << "Error: connect" << std::endl;
exit( 1 );
}
pollfd pfd;
pfd.fd = soc;
pfd.events = POLLOUT;
res = ::poll( &pfd, 1, 50000 );
if( res < 0 ) {
std::cerr << "Error: poll" << std::endl;
exit( 1 );
}
else if( res == 0 ) {
std::cerr << "Error: poll" << std::endl;
exit( 1 );
}
// Set blocking mode again
if( (arg = ::fcntl(soc, F_GETFL, NULL)) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit( 1 );
}
arg &= (~O_NONBLOCK);
if( ::fcntl(soc, F_SETFL, arg) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit( 1 );
}
return 0;
}
49999
私のマシンではポートが閉じられているため、エラーが発生することが予想されます。代わりに、プログラムは の戻り値で終了します0
。
上記のリンクにある選択の例も使用しようとしました。への呼び出しを完全な例に置き換えるとpoll()
、次のエラー メッセージが表示されます。
Operation now in progress: Operation now in progres
select を使用してコードを削減しようとしましたが、削減すると正しいconnection refused message
.
編集:
注:「操作が進行中です」というメッセージは、私の側のエラー処理コードのエラーが原因でした。これを修正すると、「getsockopt()」から正しいエラー メッセージが表示されました。これは、この例を縮小できなかった理由も説明しています。