1

シナリオ: 1 つのソケットで検出アクティビティを選択すると、以下の基準がコードで発生します。

擬似コード:

after select i am checking in
if stdin f descriptor
    do something

else if listening file descriptor
newFDescriptor = accept sockFDescriptor, (struct sockaddr *) &clientAddress, &clientAddressSize

FD_SET (new file descriptor)
send connected response to peer

// data from connected peer
else {
    receive data
}

しかし、ピアから他のピアに何かを送信するたびに、新しいファイル記述子との新しい接続が作成されます。つまり、このピア用に既に作成されたファイル記述子のデータを認識しません。ピア 1 からピア 2 (新しいファイル記述子が作成されます) ピア 1 からピア 2 (再び新しい接続) リッスンしているファイル記述子ですべてのデータを受信して​​います。

4

2 に答える 2

1

ピアが新しい接続を作成することを主張する場合、サーバー側でできることは何もありません。

「リッスンしているファイル記述子ですべてのデータを受信して​​います」というのは意味がありません。それは不可能だ。リッスンしているファイル記述子は、接続を受け入れる以外には何もできません。

于 2013-09-27T03:45:04.727 に答える
0

jedwards (+1) に同意します。開始するには、Beej のガイドを読む必要があります。

それまでの間、発生しているエラーを回避するのに役立つかもしれないいくつかの簡単な入力を次に示します。ファイル記述子を混同していると思います。

新しいファイル記述子 (accept() 呼び出しからのもの) をリストに追加し、それらを (また) 使用して、次の選択呼び出し用に fd セットを設定する必要があります。リスナー fd は、新しい接続とその後の accept() を確立するためだけのものです。その fd で receive または send を呼び出すべきではありません (server_fd と呼びましょう)。

すべての接続を配列に格納する簡単なコード例を次に示します。次に、次のように fd を設定できます。有効な fd を持たない配列のインデックスについては、-1 を使用します。

FD_ZERO(&read_fd_set);
/* Set the fd_set before passing it to the select call */
for (i=0;i < MAX_CONNECTIONS;i++) {
   if (all_connections[i] >= 0) {
       FD_SET(all_connections[i], &read_fd_set);
   }
}

ret_val = select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);

選択が返されたら、読み取りイベントを含む fd がサーバー fd であるかどうかを確認できます。そうであれば、accept() を呼び出して新しい fd を取得できます。配列に追加する必要があります。このようなもの:

if (FD_ISSET(server_fd, &read_fd_set)) { 
    new_fd = accept(server_fd, (struct sockaddr*)&new_addr, &addrlen);
    if (new_fd >= 0) {
        printf("Accepted a new connection with fd: %d\n", new_fd);
        for (i=0;i < MAX_CONNECTIONS;i++) {
             if (all_connections[i] < 0) {
                 all_connections[i] = new_fd; 
                 break;
             }
        }
    }
} 
于 2013-09-27T03:34:36.447 に答える