新しく設計されたプロトコルを使用して 1 つのサーバーを実装しています。プロトコルに従って、クライアントはヘッダーに続いてデータを送信します。ヘッダーには、データのサイズなどのメタ情報も含まれています。
サンプルクライアントを提供していますが、クライアントプログラムはサードパーティでも作成できます。したがって、ヘッダーで提供されるデータ フィールドのサイズに完全に依存することはできません。
今、私はrecv()
システムコールで1つの問題に直面しています。
#define SOCKET_CHUNK_SIZE 4096
void * value;
1 value = (void *) malloc(hdr.size);
2 total_bytes_read = 0;
3 while(total_bytes_read < hdr.size) {
4 n = recv(newsockfd, value + total_bytes_read, SOCKET_CHUNK_SIZE, 0);
5
6 //fprintf(stderr, " %ld + %d = %ld\n", total_bytes_read, n, total_bytes_read + n);
7
8 total_bytes_read += n;
9
10 if(n == 0 || n < SOCKET_CHUNK_SIZE)
11 break;
12 if(n < 0)
13 send_error_response(newsockfd);
14 }
15
16 fprintf(stderr, "%ld", total_bytes_read);
これは、少量のデータ (9420 バイトなど) では完全に機能しますが、大量のデータでは失敗します。
観察:
クライアントが 604697 バイト (hdr.size) のような大量のデータを送信できるようにします。
recv()
65280 バイトしか読み取れません。つまり、16 行目の fprintf は 65280 を出力します。呼び出しでMSG_DONTWAIT フラグを使用してみまし
recv()
たが、結果は同じです。read()
の代わりにシステムコールを使用してみましたがrecv()
、結果は同じです。6行目のコメントを外すと、完全に機能します!! (ただし、この行 (および #16 行目) はデバッグ目的でのみ使用されます。最終バージョンでは保持できません)
で MSG_WAITALL フラグを使用する
recv()
と機能しますが、最後のチャンクのサイズが SOCKET_CHUNK_SIZE (604697 = 147 * 4096 + 2585) より小さいため、最後のチャンクの読み取り中にブロックされます。したがって、クライアントからのヘッダーで提供されるサイズに依存し、で変更しない限り、このフラグを使用できませんrecv()
。
クライアントから提供されるデータはバイナリの場合もあるため、データの終わりとして何らかの表示を配置することはできません。
アイデア/ソリューションをお持ちの方ならどなたでも大歓迎です。前述したように、クライアント ヘッダーに依存する解決策がありますが、他に方法が見つからない場合にのみそれを優先します。
ラヴィ