2017-04-30 5 views
0

私はTCPクライアントはの形でTCPサーバーにデータを送信するには割り当てがあります。受け、複数のTCPセグメント

のIP_addressを\ 0port \ 0message \ nは今

、サーバー(IPアドレス10.0

printf "127.0.0.1\0004444\000Some message\n" | nc -N 10.0.2.15 3333 

しかし、割り当ての第2の部分は複数のセグメントに来るパケットを読み取ることである:私はこのような端子を介していくつかのデータを送信するとき.2.15)パケットの罰金を受け

(printf "127.0.0.1"; sleep 0.3; printf "\0004444\000"; sleep 0.3; \ 
printf "It works"; sleep 0.5; printf "\n") | nc -N 10.0.2.15 3333 

可能であれば、すべてのセグメントがバッファに格納されるように、サーバーに読み取り機能を実装する方法を教えてください。

+0

複数のセグメントに分割されていない場合、どのように実装しますか?違いはありますか?あらかじめメッセージの長さを知らないことに注意してください。 –

+0

@ n.m。私はそう簡単な読み取り関数を使用する:https://pastebin.com/RjVdVKmS – Kuyss

+0

BUF_SIZEとは何ですか? **あなたはあらかじめメッセージの長さを知らない**。 –

答えて

1

バイト数recv()の戻り値は、要求されたバイト数の1バイトから最大数バイトまでです。 TCPはバイトストリームであり、メッセージの概念を持たず、代わりにアプリケーションコードで処理する必要があります。

受信機は、何バイトのバイトが必要かを知っていなければなりません。多くのバイトが読み込まれるまでループを繰り返して読み込みます。

しかし、この状況では、受信者はメッセージの長さを送信していないため、受信者はメッセージの長さを正確に知ることができません。ソケットは、終端のある\nが出現するまでバイトごとに出力されます。例えば

char *buffer; 
int buflen, bufcap; 

int readLine(int socket, char **line) 
{ 
    char *ptr; 
    int r, idx = 0; 

    *line = NULL; 

    do 
    { 
     ptr = memchr(buffer + idx, '\n', buflen - idx); 
     if (ptr) 
     { 
      int total = ((ptr + 1) - buffer); 

      int len = (total - 1); 
      if ((len > 0) && (buffer[len-1] == '\r')) 
       --len; 

      *line = (char*) malloc(len + 1); 
      if (*line == NULL) 
       return -2; 

      memcpy(*line, buffer, len); 
      (*line)[len] = '\0'; 

      if (total < buflen) 
       memmove(buffer, buffer + total, buflen - total); 
      buflen -= total; 

      break; 
     } 

     if (buflen == bufcap) 
     { 
      int newcap = bufcap + 256; 
      char *newbuffer = (char*) realloc(buffer, newcap); 
      if (!newbuffer) 
       return -2; 
      buffer = newbuffer; 
      bufcap = newcap; 
     } 

     r = recv(socket, buffer + buflen, bufcap - buflen, 0); 
     if (r <= 0) 
      return r; 

     buflen += r; 
    } 
    while (true); 

    return 1; 
} 
:また

int readLine(int socket, char **line) 
{ 
    int r, len = 0, cap = 256; 
    char b; 

    *line = NULL; 

    char *outline = (char*) malloc(cap); 
    if (!outline) return -2; 

    do 
    { 
     r = recv(socket, &b, 1, 0); 
     if (r <= 0) 
     { 
      free(outline); 
      return r; 
     } 

     if (b == '\n') 
      break; 

     if (len == cap) 
     { 
      cap += 256; 
      char *newline = (char*) realloc(outline, cap); 
      if (!newline) 
      { 
       free(outline); 
       return -2; 
      } 
      outline = newline; 
     } 

     outline[len] = b; 
     ++len; 
    } 
    while (true); 

    if ((len > 0) && (line[len-1] == '\r')) 
     --len; 

    if (len == cap) 
    { 
     char *newline = (char*) realloc(outline, cap + 1); 
     if (!newline) 
     { 
      free(outline); 
      return -2; 
     } 
     outline = newline; 
    } 

    outline[len] = '\0'; 

    *line = outline; 

    return 1; 
} 

char *line; 
int r; 

do 
{ 
    r = readLine(cliSock, &line); 
    if (r <= 0) 
    { 
     if (r == 0) 
      printf("client disconnected\n"); 
     else if (r == -2) 
      printf("memory error\n"); 
     else 
      printf("read error\n"); 
     break; 
    } 

    // process line as needed... 

    free(line); 
} 
while (true); 

、あなたが読み、より効率的にソケットからデータを取得するとの間でデータをキャッシュ助けるために中間バッファを使用することができます

buflen = 0; 
bufcap = 256; 
buffer = (char*) malloc(bufcap); 
if (buffer) 
{ 
    char *line; 
    int r; 

    do 
    { 
     r = readLine(cliSock, &line); 
     if (r <= 0) 
     { 
      if (r == 0) 
       printf("client disconnected\n"); 
      else if (r == -2) 
       printf("memory error\n"); 
      else 
       printf("read error\n"); 
      break; 
     } 

     // process line as needed... 

     free(line); 
    } 
    while (true); 

    free(buffer); 
} 
関連する問題