2016-04-20 92 views
0

我正在編寫我的第一個客戶端/服務器程序。客戶端發送文件的名稱,服務器應發送文件(如果存在)。 服務器:不接收數據並且recv()返回0

while(1) 
    { 
     client_sock_fd = accept(listening_sock_fd, (struct sockaddr*)NULL, NULL); 
     if (client_sock_fd == -1) 
     { 
      fprintf(stderr, "ERROR: accept()\n"); 
      continue; 
     } 

     if (!fork()) 
     { 
      close(listening_sock_fd); 

      if ((numbytes = recv(client_sock_fd, buff, 1023, 0)) == -1){ 
       fprintf(stderr, "ERROR: recv()\n"); 
       return EXIT_FAILURE; 
      } 

      buff[numbytes] = '\0'; 

      FILE *f = fopen(buff, "r"); 

      if (f == NULL){ 
       if ((send(client_sock_fd, "FAIL", 4, 0)) == -1) 
       { 
        fprintf(stderr, "ERROR: send()\n"); 
       } 
      }else { 

       if ((send(client_sock_fd, "OK", 2, 0)) == -1) 
       { 
        fprintf(stderr, "ERROR: send()\n"); 
       } 

       char * buffer = 0; 
       long length; 


       fseek (f, 0, SEEK_END); 
       length = ftell (f); 
       fseek (f, 0, SEEK_SET); 
       if((buffer = malloc (length)) == NULL){ 
        fprintf(stderr, "ERROR: malloc()\n"); 
        exit(1); 
       } 
       if (buffer) 
       { 
        fread (buffer, 1, length, f); 
       } 
       fclose (f); 


       char str[1024]; 
       sprintf(str, "%d", (int)strlen(buffer)); 
       if ((send(client_sock_fd, str, strlen(str), 0)) == -1) 
       { 
        fprintf(stderr, "ERROR: send()\n"); 
       } 

       int s = sendall(client_sock_fd, buffer, strlen(buffer)); 
       if (s == -1){ 
        fprintf(stderr, "ERROR: send()\n"); 
        free(buffer); 
        exit(1); 
       } 


       free(buffer); 
      } 

      close(client_sock_fd); 
      exit(0); 
     } 
     close(client_sock_fd); 
    } 

int sendall(int s, char *buf, int len) 
{ 
    int total = 0; 
    int bytesleft = len; 
    int n; 

    while(total < len) { 
     n = send(s, buf+total, bytesleft, 0); 
     if (n == -1) { break; } 
     total += n; 
     bytesleft -= n; 
    } 

    return n==-1?-1:0; 
} 

客戶:

if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ 
     fprintf(stderr, "ERROR: chyba pri socket()\n"); 
     return EXIT_FAILURE; 
    } 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(args.port_num); 

    if ((prlHst = gethostbyname(argv[args.host_name])) == NULL){ 
     fprintf(stderr, "ERROR: gethostbyname()\n"); 
     return EXIT_FAILURE; 
    } 

    memcpy(&serv_addr.sin_addr, prlHst->h_addr_list[0], prlHst->h_length); 

    if (connect(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){ 
     fprintf(stderr, "ERROR: connect()\n"); 
     return EXIT_FAILURE; 

if ((send(sock_fd, argv[args.file], strlen(argv[args.file]), 0)) == -1){ 
     fprintf(stderr, "ERROR: send()\n"); 
     return EXIT_FAILURE; 
    } 

    if ((numbytes = recv(sock_fd, buff, 1023, 0)) == -1){ 
     fprintf(stderr, "ERROR: recv()\n"); 
     return EXIT_FAILURE; 
    } 

    buff[numbytes] = '\0'; 

    FILE *fp = fopen(argv[args.file], "w"); 
    if (fp == NULL){ 
     fprintf(stderr, "ERROR: fopen()\n"); 
     return EXIT_FAILURE; 
    } 
    if (!strcmp(buff, "OK")){ 
     if ((numbytes = recv(sock_fd, buff, 1023, 0)) == -1){ 
      fprintf(stderr, "ERROR: recv()\n"); 
      return EXIT_FAILURE; 
     } 

     char *pEnd; 
     long int dataToRead = strtol(buff, &pEnd, 10); 
     long int readData = 0; 

     fprintf(stderr, "data to read %lu\n", dataToRead); 

     while (readData < dataToRead) { 
      unsigned char buffer [4096] = {0}; 
      int nbuffer; 
      for (nbuffer = 0; nbuffer < 4096;) { 

       int len = recv(sock_fd, buffer, 4096, 0); 
       if (len == -1){ 
        fprintf(stderr, "ERROR: recv()\n"); 
        return EXIT_FAILURE; 
       } 
       /* FIXME: Error checking */ 

       nbuffer += len; 
       readData += len; 

      } 

      fwrite(buffer, sizeof(unsigned char), nbuffer, fp); 
     } 

一切工作正常,直到客戶while循環。 recv始終返回0。這是爲什麼?我的代碼有什麼問題?我試圖寫一個send發送到想要的文件,並收到它。我也檢查了dataToRead變量,沒關係,包含期望值。感謝您的回覆!

+0

返回值通常表示套接字已關閉。在客戶端,你在哪裏初始化套接字?無法在您的代碼示例中看到它。 –

+0

好吧,你找到文件,得到它的長度,爲整個文件分配一個'length'大小的緩衝區,(一般來說不是一個好主意),然後......不可避免地,回退到使用strlen(buffer)下面的代碼:((你已經知道了長度,那麼爲什麼在strlen()調用上浪費時間,並且讓你的代碼無法處理空字節數據呢? –

+0

@JonathonOgden我添加了初始化@jxh我試着用一個文件包含5個字符,所以'dataToRead'中的值爲'6' –

回答

0

一切正常,直到客戶端中的while循環。 recv總是返回0. 這是爲什麼?

這意味着對方已關閉連接。

我的代碼有什麼問題?

你沒有意識到條件,關閉套接字並停止嘗試讀取它。當recv()返回0時,或者確實當它返回-1時,您必須執行此操作,而errno等於除EAGAIN/EWOULDBLOCK之外的任何值。

我試圖寫一些東西到想要的文件發送與一個發送和它收到。我也檢查了dataToRead變量,它沒問題,包含期望值。

我不明白這與它有什麼關係。

你的副本循環過於複雜。從插座在插座上傳送字節到一個文件,直到流的結尾的規範的方法如下:

while ((count = recv(socket, buffer, sizeof buffer)) > 0) 
{ 
    write(file, buffer, count); 
} 

以及相反地用於從文件傳送字節到插座:

while ((count = read(file, buffer, sizeof buffer)) > 0) 
{ 
    send(socket, buffer, count); 
} 
相關問題