12

ブロッキングソケットがあります(少なくとも次のコードではそう見えます):

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
            ERROR("%s: error opening socket", __func__);
            return (RESP_ERROR);
    }

    t.tv_sec = timeout;
    t.tv_usec = 0;

    int rf = fcntl(sock, F_GETFD);
    ERROR("fcntl ret=%d, ret & O_NONBLOCK = %d", rf, rf & O_NONBLOCK);

    if ((setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&t, sizeof (t)) < 0)
        || (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&t, sizeof (t)))) {
            strerror_r(errno, err, 254);
            ERROR("%s: error on setsockopt -> %s", __func__, err);
            close(sock);
            return (RESP_ERROR);
    }

    rf = fcntl(sock, F_GETFD);
    ERROR("after select fcntl ret=%d, ret & O_NONBLOCK = %d", rf, rf & O_NONBLOCK);

    if (connect(sock, (struct sockaddr *)&dst, sizeof (dst)) != 0) {
            strerror_r(errno, err, 254);
            ERROR("%s: error on connect -> %s", __func__, err);
            close(sock);
            return (RESP_ERROR);
    }

そして、これはログからです:

3 月 6 日 10:42:04 tcpclient: fcntl ret=0、ret & O_NONBLOCK = 0

Mar 6 10:42:04 tcpclient: fcntl ret=0 を選択した後、ret & O_NONBLOCK = 0

Mar 6 10:42:14 tcpclient: 認証: 接続エラー -> 操作が進行中

これはブロッキング ソケットのようですが、非ブロッキングに典型的なエラーを返しますか? Linux は 2.6.18-308.el5 です。何か案は?

4

2 に答える 2

8

への呼び出しtimeoutでない場合は、タイムアウトして戻ります。これは、接続が確立されたかどうかに関係なく発生します。0connect()

タイムアウトの期限が切れた瞬間から、connect()ノンブロッキング ソケットで呼び出されたかのように動作します。

このケースを参照してください(以下の「すぐに」から逐語的man connectに無視します):

EINPROGRESS

ソケットはノンブロッキングであり、接続をすぐに完了できません。書き込み用のソケットを選択することで、(2) または poll(2) を選択して完了することができます。select(2) が書き込み可能であることを示した後、getsockopt(2) を使用してレベル SOL_SOCKET で SO_ERROR オプションを読み取り、connect() が正常に完了したか (SO_ERROR がゼロ)、失敗したか (SO_ERROR はここにリストされている通常のエラー コードの 1 つです。失敗の理由)。


ところで:誰かがこれが標準的な動作であることを確認できますか?これについてはどこかに明示的に言及されていますか?

man 7 socket状態 (イタリック体は私):

SO_RCVTIMEO と SO_SNDTIMEO

エラーが報告されるまでの受信タイムアウトまたは送信タイムアウトを指定します。[...] データが転送されず、タイムアウトに達した場合、-1 が返され、errno が EAGAIN または EWOULDBLOCK に設定されます。これは、ソケットが nonblocking であると指定された場合と同様です。[...] タイムアウトは、ソケット I/O を実行するシステム コール (read(2)、recvmsg(2)、send(2)、sendmsg(2) など) に対してのみ有効です。タイムアウトは、select(2)、poll(2)、epoll_wait(2) などには影響しません。

についての言葉がconnect()ないので、私の答えが当てはまるかどうかはわかりません。

于 2013-03-06T10:13:17.920 に答える
2

で試してみてくださいif (connect(...) < 0)。エラーがまったく発生していない可能性があります。

NBブロッキングモードがデフォルトです。設定する必要はありません。

于 2013-03-06T20:22:08.387 に答える