データグラムソケットを監視するスレッドでselect()を使用していますが、スレッドが開始する前にデータがソケットに送信されていない限り、select()は0を返し続けます。なぜ、データがすでに送信されている場合、選択はファイルディスクリプタを準備完了として表示するのですか?
私はCとC++はほとんどありません。
bool RelayStart() {
sock_recv = socket(AF_INET, SOCK_DGRAM, 0);
memset(&addr_recv, 0, sizeof(addr_recv));
addr_recv.sin_family = AF_INET;
addr_recv.sin_port = htons(18902);
addr_recv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sock_recv, (struct sockaddr*) &addr_recv, sizeof(addr_recv));
isRelayingPackets = true;
NSS::Thread::start(VIDEO_SEND_THREAD_ID);
return true;
}
スレッドを停止する方法:
bool RelayStop() {
isSendingVideo = false;
NSS::Thread::stop();
close(sock_recv);
return true;
}
とスレッド内のメソッドを実行します。ここでスレッドを開始する方法があります
void Run() {
fd_set read_fds;
int select_return;
struct timeval select_timeout;
FD_ZERO(&read_fds);
FD_SET(sock_recv, &read_fds);
while (isRelayingPackets) {
select_timeout.tv_sec = 1;
select_timeout.tv_usec = 0;
select_return = select(sock_recv + 1, &read_fds, NULL, NULL, &select_timeout);
if (select_return > 0 && FD_ISSET(sock_recv, &read_fds)) {
// ...
}
}
}
問題は、もし存在していますRelayStart()が呼び出される前にすでにUDPパケットをポート18902に送信しているプロセスではないため、select()は常に0を返します。たとえば、スレッドを再起動せずに送信者を再起動することはできませんrder。
送信者が最初に開始されている限り、すべてうまくいくようです。
'socket()'と 'bind()'がエラーを報告していないことを確認しましたか?あなたのコードにはエラーチェックがありません。また、スレッドが実行中にソケットがエラーを報告している場合に 'select()'を呼び出すときに例外 'fd_set'を含むようにしてください。 –
エラーは例外セットには表示されませんが、奇妙なことですが、読み取りセット内にあります。帯域外データのみが例外セットに現れます。 – geekosaur
私は堅牢なエラーチェックをしていない間、select()の戻り値を見ていましたが、一貫して0(エラーではありません)でした。 – Matt