2012-04-20 4 views
2

でと呼ばれるには、以下の問題を得ました。しかしselectは、ソケットに「クライアント切断」などのエラーが発生した場合でもクライアント(インデックスはFD_SET)を返します。)(RECV前にエラーをチェック

recv()を呼び出さずにソケットをチェックすることは可能ですか?

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

さて、私は再びバッファを解放する必要があり、それはかなり無駄だった:私は「バッファプール

サンプル・コードのうちのバッファを取得する必要が受信するので、私のプールの1つのバッファの

(短時間)だから、RECV()

答えて

0

いくつかの仕事の分、あなたの助けた後、私はちょうど全額を受信する前に1バイトの受信にします。if:

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 
1

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

0

recvなどの機能を呼び出すことは、ネットワーキングデバイスなどでは直接機能しません。 データを送受信するときは、使用可能なデータがあるかどうかOSに問い合わせるか、データを送信待ちにするだけです。その後、あなたのコードがすでに進んでいる場合、OSはもう1つの仕事をします。 これは、OSネットワーキング層に「接触する」ソケット機能の次の呼び出しの後にエラーを受け取る理由です。

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

しかし、ソケットをブロックしてバッファを無駄にするのを防ぐには、ソケットを使って非同期的に動作する方法を提供するオンラインライブラリの実装テクニックをチェックしてください。あなたは実際の受信を行う必要があります。

また、ストリームベースのレイヤーであるため、TCPレイヤーを介して結合または分割されたデータの問題に直面するため、大量のデータを一度に受け取るのは良い技術ではありません。あなたのパケット(数バイト)にヘッダを入れて、それを受信することをお勧めします。ヘッダーのためにプルする必要はありませんが、ヘッダーの後にヘッダーの長さに基づいて残りのメッセージを読み込みます。これはほんの一例です。

3

私は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; 
} 

UPDATE:Windowsは、あまりにもそれをサポートしているようthis documentによると

、それはそうです。

+0

残念ながらERR_CODEが毎回0である、また、(RECV場合は)0(エラー) – Aurus

+0

@Aurusを返します。 0を返し、recvが0を返したら、おそらくEOFが返ってきます(つまり、相手側が接続を閉じたとします)。 –

+0

でも、クライアント接続がまだ生存している場合は0になります。 – Aurus

関連する問題