0

クライアント側で一度に 1 行しか受信できないという問題があります。ストリーム全体を一度に受信する方法を見つけようとしています。受信の問題に関して私が持っているものを誰でも修正できますか? クライアント コードと、関係があると思われるサーバー側コードの一部を含めました。

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>


int main(int argc, char *argv[])

{
    FILE *log;
    int opt;
    int count = 0;
    int sock, bytes_received;
    char send_data[2048],recv_data[2048];
    struct hostent *host;
    struct sockaddr_in server_addr;

    if(remove("client_log")) ;

    if(argc == 2)
    {
      if(strcmp(argv[1], "-v") == 0)
      {
        log = fopen("client_log", "a");
        opt = 1;
      }
      else if(strcmp(argv[1], "-V") == 0)
      {
        log = fopen("client_log", "a");
        opt = 2;
      }
    }

    }
    else
      opt = 0;

    host = gethostbyname("127.0.0.0");

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket");
        exit(1);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(noneya);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(server_addr.sin_zero),8);

    if (connect(sock, (struct sockaddr *)&server_addr,
                sizeof(struct sockaddr)) == -1)
    {
        perror("Connect");
        exit(1);
    }

    while(1)
    {

      bytes_received=recv(sock,recv_data,2048,0);
      recv_data[bytes_received] = '\0';

      if (strcmp(recv_data , "q") == 0 || strcmp(recv_data , "Q") == 0)
      {
       close(sock);
       break;
      }

       else
      {
        if(opt != 0)
          fprintf(log, "\n Received Data: %s \n", recv_data);
        if(opt == 2)
          printf("\nReceived Data: %s \n" , recv_data);
      }

       if(count == 0)
       {
         printf("Pick an option: \n");
         printf("1 - to search by Department only\n");
         printf("2 - to search by Department and Class Number\n");
         printf("3 - to search more specifically\n");
         printf("q or Q - to Quit");
       }
       printf("\nSEND: ");
       gets(send_data);
       if(count == 0)
       {
         count = (int)send_data;
         if(count == 3)
            count++;
       }
       else if(count > 0)
         count--;

        if(opt != 0)
          fprintf(log, "\n Sending Data: %s \n", send_data);
        if(opt == 2)
          printf("\n Sending Data: %s \n" , send_data);

      if (strcmp(send_data , "q") != 0 && strcmp(send_data , "Q") != 0)
       send(sock,send_data,strlen(send_data), 0);

       else
      {
       send(sock,send_data,strlen(send_data), 0);
       close(sock);
       break;
      }

    }
return 0;
}

クライアント側は次のとおりです。

 case 1:

            fread(data, sizeof(sched_record), MAX_RECORD, filePointer);
            fclose(filePointer);
            char send_data[] = "Enter Department Name";
            send(connected, send_data, strlen(send_data), 0);
            bytes_received = recv(connected, recv_data, BUF, 0);
            recv_data[bytes_received] = '\0';
            strcpy(tempDept, recv_data);
            for (i=0; i<MAX_RECORD; i++){
                if ((strcmp(tempDept, data[i].Dept)==0) && tempCourse != data[i].course){
                        sprintf(send_data,"%s %d", data[i].Dept, data[i].course);
                        send(connected, send_data, strlen(send_data), 0);
                        tempCourse = data[i].course;

                }
            }
        break;

必要に応じて、さらに情報を提供できます。サーバー側は大丈夫だと思います。-Wall と -Wextra を使用してコンパイルしましたが、警告は表示されませんでした。

4

2 に答える 2

3

一度に 1 行ずつ送信されるため、一度に 1 行ずつデータを受信して​​います。しかし、それがこのように出てくるという事実は、純粋な運です。TCP ストリームは、クライアントの TCP スタックによって、または相手側のバッファリングによって、任意に分割および再結合できます。たとえば、各行の前にカウントを送信したり、\n行の最後に送信したりするなど、ストリーム内に何らかの形式の明示的なフレーミングが必要です。

于 2012-05-03T15:53:46.887 に答える
1

ダスクワフの答えを追加すると、ここで遭遇したのは、ストリームベースのプロトコルを使用する必要があるということです。

TCP はメッセージ指向ではないため (UDP や他のより風変わりなメッセージ プロトコルとは異なり)、単一のバイト ストリームを送受信しています。基本的に、クライアントを本のライターと見なし、サーバーをそのリーダーと見なす場合、TCP の世界ではすべての句読点が削除されます :)。

プログラマーの仕事は、あるメッセージ/フレームが終了し、次のメッセージが開始する場所をエンコードおよび/または埋め込むことができる明確に定義された方法を提供することです。改行を使用するのが最も簡単な方法ですが、TCP ベースのプロトコルでは、長さ、区切り文字、またはそれらの組み合わせを使用します (HTTP を参照)。

于 2012-05-03T19:54:16.013 に答える