6

並列スレッドでのソケット API ( recvsendselect、など) の使用法を理解しようとしています。closeこれは、2 つの並列スレッドで 1 つのソケット ファイル記述子を使用することを意味します。私はこの質問を経験しました。それでも、マルチスレッドでのソケット API の使用法を説明する標準ドキュメントを見つけることができません。opengroupの man ページでさえ、これについて何も語っていません。

また、以下にリストされている並列スレッドの使用シナリオが POSIX ソケット API で有効かどうかも知りたいです。

recv1)およびsend2 つの並列スレッドでの呼び出し

int main_thread() {
    fd = do_connect(); //TCP or UDP
    spawn_thread(recv_thread, fd);
    spwan_thread(send_thread, fd);
    ...
}

int recv_thread(fd) {
    while(1) {
        recv(fd, ..)
        ...
    }
}

int send_thread(fd) {
    while(1) {
        send(fd, ..)
        ...
    }
}

2) 2 つの並列スレッドでrecvand sendwithを呼び出すselect

int recv_thread(fd) {
    while(1) {
        select(fd in readfd)
        recv(fd, ..)
        ...
    }
}

int send_thread(fd) {
    while(1) {
        select(fd in write)
        send(fd, ..)
        ...
    }
}

3) 2 つの並列スレッドで, ,を使用してrecvandsendを呼び出すsetsockoptioctlfcntl

int recv_thread(fd) {
    int flag = 1
    while(1) {
        ioctl(fd, FIONBIO, &flag); //enable non block
        recv(fd, ..)
        flag = 0;
        ioctl(fd, FIONBIO, &flag); //disable non block
        ...
    }
}

int send_thread(fd) {
    while(1) {
        select(fd in write)
        send(fd, ..)
        ...
    }
}
4

1 に答える 1

3

Posix 関数は「デフォルトで」スレッドセーフです:

2.9.1 スレッドセーフ

POSIX.1-2008 のこの巻で定義されているすべての関数は、スレッドセーフである必要がありますが、次の関数はスレッドセーフである必要はありません。

多くの人がすでにコメントしているように、言及された呼び出しを別のスレッドから安全に呼び出すことができます。

ケース "1" と "2" は、製品コードの非常に典型的なものです (1 つのスレッドが受信し、1 つの送信があり、各スレッドが との多数の接続を処理しselect()ます)。

ケース "3" はどこか奇妙で、おそらく問題の原因となります (動作し、呼び出しは有効ですが、目的の動作を取得するのは簡単ではない可能性があります)。通常、最初にソケットを非ブロッキング モードにして、send()/recv()呼び出しまたはブロッキングで EAGAIN/EWOULDBLOCK エラーを処理し、 // / を使用しselect()ます。pselect()poll()ppoll()

この場合の送信スレッドは、ブロック モードまたは非ブロック モードのソケットをランダムに「検出」します。

于 2016-03-31T08:58:28.467 に答える