2011-06-21 17 views
1

は、私は巨大なバッファサイズを持っていると私はそれは、クライアントが送信されたすべてのものを受け取ることになりますと仮定しました。 しかし、私はパケットセグメンテーションのような問題に直面しました。読み取りハンドル問題

クライアントが500バイトを送信したのに何とか2つの250バイトのパケットがある場合、この状況を処理する方法はありません。

私はオンライン見上げると、このコード

int handle_read(client *cli, struct epoll_event *ev) { 
    size_t len = 4096; 
    char *p; 
    ssize_t received; 

    cli->state = 1; 
    if (cli->buffer != NULL) { 
     //free(cli->buffer); 
     //printf("Buff not null %s\n", cli->buffer); 
    } 

    //allocate space for data 
    cli->buffer = (char*)malloc((size_t)(sizeof(char) * 4096)); 
    p = cli->buffer; 

    do { //read until loop conditions 
     received = recv(ev->data.fd, p, len, 0); 
     if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { 
      //if error, remove from epoll and close socket 
      printf("Handle error!!!\nClient disconnected!\n"); 
      epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->data.fd, ev); 
      close(ev->data.fd); 
     } 
     p = &cli->buffer[received]; 
    } while (received >= len && errno != EAGAIN && errno != EWOULDBLOCK); 

    return received; 
} 

を見つけたあなたたちはそれを受けながら、すべての例外が起こるかもしれない扱いと思いますか?また、ソケット例外を扱うチュートリアルやサンプルを教えてください。サンプルコードはオンラインでは詳細をカバーしていません。事前にお礼します。

答えて

1

recvは物事のいずれかを返すことができ、そして、あなたのコードが正しくそれぞれを処理する必要がある:

1)正の数を。これは、何バイトかを読み込むことを意味します。

2)負の数。これは、「エラー」が発生したことを意味します。

3)ゼロ。つまり、接続のもう一方の端は、ソケット上で成功したshutdown()(またはclose())を実行しました。 (一般的には、読み取りから0のリターン()またはRECV()EOFを意味します。)

「エラー」の場合は、さらに「EAGAINまたはEWOULDBLOCK」に分解し、「他のすべて」。最初の2つは、それが非ブロッキングソケットであることを意味し、この時点であなたに与えるデータはありませんでした。忙しい待ち時間を避けるために、poll()(またはselect()またはepoll())をもう一度呼び出すといいでしょう。

「その他のすべて」は実際のエラーを意味します。あなたもそれらを処理する必要があります。完全なリストはPOSIX spec for recv()を参照してください。

これを考えると、サンプルコードはいくつかの理由で悪いと言えます。 0(閉じた接続)は正しく処理されません。エラーを処理しません。 recv()EAGAIN/EWOULDBLOCKを返すと、ビジーループが発生します。

ああ、それはsizeof(char)を使用しています。これは、CまたはC++プログラミング言語に精通していない人が書いた確実な記号です。

+0

ご返信ありがとうございます。あなたは良いサンプルコードやチュートリアルを知っていますか?私はオンラインで見て、彼らは基本的なものだけをカバーしました。前もって感謝します。 – codereviewanskquestions

+0

私はいつも自分自身を転がします。これは非常にシンプルなネストされたif/then構造ですべてのケースを処理しますが、各ケースを処理する方法は特定のアプリケーションによって異なります。 (特に、エラー。コードを返すか、例外をスローするのですか?それはあなたの慣習によります) – Nemo

+0

答えをありがとう。 – user800799

0

ノーマルで「クライアントが送信したデータ数」を知ることはできません。スケーラブルなデータ形式(ヘッダーにデータ長を持つ)またはデータトークンの区切り記号を使用する必要があります。たとえば、データと次のデータの間に\ xffを追加することができます。または、固定データ形式を使用する必要があります。

関連する問題