0

関数から返されたクライアント ソケットのソケット オプションを設定しようとしていaccept()ます。しかし、それらは正しく設定されていません。

私の目的は、特定の時間非アクティブになった後にクライアントをタイムアウトにすることです。ただし、サーバーは引き続き他のクライアント接続を受け入れることができるはずです。

以下は、ソケットオプションを設定するコードです。何が間違っているのか教えてください。

while ((new_sock_fd = accept(socket_fd, (struct sockaddr *) &cli_addr, &clilen)) > 0)
{
    if (new_sock_fd < 0)
        printf("Accept Error");
    else
    {
        struct timeval timeout;      
        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        if (setsockopt(new_sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
            error("setsockopt failed\n");
        if (setsockopt(new_sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
            error("setsockopt failed\n");
        pthread_create(&thread, NULL, client_handler, (void *) (intptr_t)new_sock_fd); //intptr_t is big enough to hold the integer prt
    }
}
4

1 に答える 1

1

私の目的は、特定の時間非アクティブになった後にクライアントをタイムアウトにすることです。[...]何が間違っているのか教えてください..?

SO_RCVTIMEO と SO_SNDTIMEO の意図を誤解していると思われます。マニュアルページから:

SO_RCVTIMEO および SO_SNDTIMEO エラーが報告されるまでの受信タイムアウトまたは送信タイムアウトを指定します。引数は構造体 timeval です。入力関数または出力関数がこの期間ブロックされ、データが送信または受信された場合、その関数の戻り値は転送されたデータの量になります。データが転送されず、タイムアウトに達した場合は、-1 が返され、errno が EAGAIN または EWOULDBLOCK、または EINPROGRESS (connect(2) の場合) に設定され、ソケットが非ブロッキングに指定されているかのようになります。タイムアウトがゼロ (デフォルト) に設定されている場合、操作はタイムアウトしません。

...しかし、あなたが望むのは、TCP接続にトラフィックがない状態で一定時間後にTCP接続が自動的に閉じられるようにすることです。これは、 send() または recv() への呼び出しを強制するのと同じではありません一定時間後に戻る。

探しているものがアイドル状態の TCP 接続を閉じるメカニズムである場合は、ソケットでデータが送受信されるたびに現在の時刻を記録することで、それを自分で実装できます。後で (たとえば、send() または recv() がタイムアウトした後)、記録された最後に見られたトラフィックを現在の時刻から差し引くことができます。差がアイドル タイムアウト値よりも大きい場合は、自分でソケットに対して close() を呼び出します。

于 2016-09-07T04:38:03.097 に答える