2

次の問題が発生しました。

select ()を使って複数接続できるサーバーを作りました。ただし、ソケットが「クライアントの切断」などのエラーを受け取った場合にも、selectはクライアント ( FD_SETのインデックス) を返します。

recv ()を呼び出さずにソケットをチェックすることは可能ですか? 受信するには、「 BufferPool」からバッファを取得する必要があるためです

サンプルコード:

int ret = recv(client, buffer_pool->get(), BUFFER_SIZE, 0);
if(ret == -1) ... // something went wrong

それでは、もう一度バッファを解放する必要があります。これは、プール内の 1 つのバッファをほとんど無駄にしていました。(短い時間に)

recv () を呼び出さずにソケットを確認することはできませんか?

4

5 に答える 5

4

Windows についてはよくわかりませんが、getsockopt()POSIX 準拠のシステムでは魅力的に機能します。ただし、使用する前に、プールからバッファを取得する方が、追加のシステム コールを行うよりもコストがかかることを確認してください。コード スニペットを次に示します。

int my_get_socket_error(int fd)
{
        int err_code;
        socklen_t len = sizeof(err_code);

        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err_code, &len) != 0)
                err_code = errno;
        else
                errno = err_code;
        return err_code;
}

アップデート:

このドキュメントによると、Windowsでもサポートされているようです。

于 2012-04-20T15:44:21.757 に答える
2

いいえ、recv()電話を避ける方法はありません。ソケットが読み取り可能であると報告された場合select()は、ソケットから読み取り、新しい状態を判別する必要があります。クライアントが正常に切断された場合、recv()-1ではなく0を返します。プールされたバッファを無駄にしたくない場合は、最初に一時ローカルバッファに読み込む必要があります。次に、recv()データが返される場合は、プールされたバッファを取得して、読み取ったデータをそのバッファにコピーできます。

于 2012-04-20T15:27:46.990 に答える
1

recvおよび同様の機能を呼び出すことは、ネットワークデバイスまたは同様のものでは直接機能しません。データを送受信するときは、OSに利用可能なデータを問い合わせるか、送信のためにデータをキューに入れるだけです。その後、コードがすでに進んでいるときに、OSが他の仕事をします。そのため、OSネットワーク層に「接続」するソケット関数を次に呼び出した後にエラーが発生します。

その点でエラーが発生するのは正常であり、対処する必要があります。

ただし、ソケットのブロックやバッファの浪費を防ぐために、ライブラリを実装または準備するオンラインテクニックを確認してください。これにより、ソケットを非同期で操作できます。これにより、ソケットが受信コールバック関数をトリガーする前に何も定義する必要がなくなります。実際の受信。

また、ストリームベースのレイヤーであるため、TCPレイヤーを介してマージまたは分割されたデータで問題が発生するため、一度に大量のデータを受信することは適切な手法ではありません。パケット(数バイト)にヘッダーを入れて受信することをお勧めします。そうすれば、ヘッダーをプルする必要はありませんが、ヘッダーの後にのみ、ヘッダーで指定された長さに基づいて残りのメッセージを読み取ります。これは単なる可能な例です。

于 2012-04-20T15:38:47.130 に答える
0

数分間の作業とあなたの助けの後、全額を受け取る前に 1 バイトを受け取りました。

SOCKET client = ...;

char temp = 0x00;
int len = recv(client, &temp, 1, 0);
if(len == 0)
{
    // .. client error handling
    return;
}

char* buffer = m_memory_pool->Get();
len = recv(client, buffer + 1, m_memory_pool->buffer_size() - 1, 0);
buffer[0] = temp;

// data handling
于 2012-04-21T11:44:23.983 に答える