【问题标题】:client can't read after connection with server in tcp客户端在 tcp 中与服务器连接后无法读取
【发布时间】:2015-04-13 06:13:07
【问题描述】:

我为一个 tcp 程序编写了读写函数。我在服务器端输出,但在客户端无法读取。我的代码

读取功能:

 int read_data (int sd , char **data_buf)
 {
    int in_length,length,size,bytesread;
    char *temp_buf;

    size = read(sd,&in_length,sizeof(in_length));/*send entire length of data*/

    if( 0 > size )
    {
            printf("Error on reading from socket\n");
            exit(1);
    }

    length = ntohl(in_length);

    printf("Total length coming : %d\n",length);

    *data_buf =(char *)malloc((length+1)*sizeof(char));
    temp_buf =(char *)malloc((length+1)*sizeof(char));

    while(length> 0)
    {
      bytesread = read(sd,temp_buf,4);
      strcat(*data_buf,temp_buf);
      temp_buf = temp_buf + bytesread;
      length = length - bytesread;
    }


    return 1;
 }

我的写作功能为:

  int write_data (int sd , char *buffer)
  {
    int length,len_buff,bytesread,size;

    len_buff = strlen(buffer);/*total length of string*/
    printf("string  == %s\n",buffer);
    length = htonl(len_buff);/*convert to host to n/w*/

    printf("Total length send =%d\n",len_buff);

    size = write(sd,&length,sizeof(length));/*write total size to server */

    if( 0 > size)
    {
            printf("error\n");
            exit(0);
    }

    while(length > 0)
    {
      bytesread = write(sd,buffer,4);/*write 4 bytes to server*/
      buffer = buffer + bytesread;
      length = length - bytesread;
    }

    return 1;
  }

客户端程序:

 ///.............code for socket and connections.................//
 ret = write_data(sd,user_string);/*write entire datas to server*/
  value_from_server = read_data(sd,&data_buf);

服务器端程序:

 value_from_client = read_data(connfd,&data_buf);
 printf("the value from client : %s\n",data_buf);

 index = string_function(data_buf,&store_buf);

 printf("after string process : %s\n",store_buf);

  write_data(connfd,store_buf);

  printf("i am waiting for next string\n");

connfd 是用于与客户端通信的新套接字。读写功能在服务器端完美运行。编写功能在客户端工作。但从服务器读取在客户端程序中不起作用。我的代码有错误吗?

【问题讨论】:

    标签: c sockets tcp


    【解决方案1】:
    bytesread = read(sd,temp_buf,4);
    

    为什么总是在循环内读取 4 个字节?您应该正在读取要读取的剩余字节数。套接字正在阻塞,因此如果服务器完成发送但客户端仍然尝试读取 4 个字节以在最后一次迭代中到达,则会卡住。

    在循环内有打印语句以了解每次迭代中读取的字节数,并查看客户端是否被 read 阻塞

    【讨论】:

    • 可能是客户端发送了足够的字节让read返回并退出循环?
    【解决方案2】:

    您的代码有几个逻辑错误。

    size = read(sd,&in_length,sizeof(in_length));/*send entire length of data*/
    if( 0 > size )
    {
            printf("Error on reading from socket\n");
            exit(1);
    }
    length = ntohl(in_length);
    

    在这里,您假设您读取了四个字节,而不是更少,或者是流的结尾。您必须检查流的结尾(返回值为零),并且必须循环直到获得四个字节。

    while(length> 0)
    {
      bytesread = read(sd,temp_buf,4);
      strcat(*data_buf,temp_buf);
      temp_buf = temp_buf + bytesread;
      length = length - bytesread;
    }
    

    在这里,您再次忽略了流结束或错误的可能性。应该是:

    while ((bytesread = read(sd,temp_buf, length)) > 0)
    {
        temp_buf += bytes_read;
        length -= bytesread;
    }
    if (bytesread < 0)
    {
        perror("read 2");
    }
    else if (length > 0)
    {
        // end of stream before all expected bytes were received ...
    }
    else
    {
        // The OK case
    }
    

    您的发送代码不是最理想的:

    while(length > 0)
    {
      bytesread = write(sd,buffer,4);/*write 4 bytes to server*/
      buffer = buffer + bytesread;
      length = length - bytesread;
    }
    

    将写入分块为 4 字节是没有意义的。应该是:

    while (length > 0)
    {
      bytesread = write(sd, buffer, length);
      buffer = buffer + bytesread;
      length = length - bytesread;
    }
    

    当然,错误命名的bytesread 变量应该被称为byteswritten. 实际上你可以依赖这个循环只执行一次。同样,它应该接着测试byteswritten == -1 以检查错误。

    【讨论】:

      【解决方案3】:

      您的函数中存在逻辑错误。

      读取循环在每次迭代中准确读取 4 个字节。如果正在读取的数据长度不是 4 的偶数倍read() 将在最后一次迭代中阻塞,等待未到达的数据。读取循环还假设read() 返回一个以空值结尾的缓冲区,但事实并非如此,因此strcat() 将尝试从周围的内存中复制数据,并且将复制垃圾或因段错误而崩溃。此外,读取函数返回给调用者的数据缓冲区不是空终止的,而是调用者假定它是空终止的。

      写入循环在每次迭代中恰好写入 4 个字节。如果数据的长度不是4 的偶数倍write() 将尝试在最后一次迭代中从周围的内存中写入数据,并且将发送垃圾或因段错误而崩溃。 p>

      您也没有在任一函数中进行足够的错误处理。

      试试类似的方法:

      void read_raw_bytes (int sd, void *data, int length)
      {
          int bytes_read;
          char *data_ptr;
      
          data_ptr = (char*) data;
      
          while( length > 0 )
          {
              bytes_read = read(sd, data_ptr, length);
              if( bytes_read < 0 )
              {
                  printf("Error on reading from socket\n");
                  exit(1);
              }
      
              if( bytes_read == 0 )
              {
                  printf("Disconnected while reading from socket\n");
                  exit(1);
              }
      
              data_ptr += bytes_read;
              length -= bytes_read;
          }
      }
      
      void write_raw_bytes (int sd, void *data, int length)
      {
          int bytes_sent;
          char *data_ptr;
      
          data_ptr = (char*) data;
      
          while( length > 0 )
          {
              bytes_sent = write(sd, data_ptr, length);
              if( bytes_sent < 0 )
              {
                  printf("Error on writing to socket\n");
                  exit(0);
              }
      
              data_ptr += bytes_sent;
              length -= bytes_sent;
          }
      }
      
      int read_data (int sd, char **data_buf)
      {
          int length;
      
          read_raw_bytes (sd, &length, sizeof(length)); /*send entire length of data*/
          length = ntohl(length);
          printf("Total length coming : %d\n", length);
      
          *data_buf = (char *) malloc((length+1)*sizeof(char));
          if (*data_buf == NULL)
          {
              printf("Error on allocating memory\n");
              exit(1);
          }
      
          read_raw_bytes (sd, *data_buf, length);
          (*data_buf)[length] = 0;
      
          return 1;
      }
      
      int write_data (int sd, char *buffer)
      {
          int length, len_buff;
      
          len_buff = strlen(buffer); /*total length of string*/
          printf("string  == %s\n", buffer);
          printf("Total length send =%d\n", len_buff);
      
          length = htonl(len_buff); /*convert to host to n/w*/
          write_raw_bytes (sd, &length, sizeof(length)); /*write total size to server */
          write_raw_bytes (sd, buffer, len_buff);
      
          return 1;
      }
      

      【讨论】:

      • read() 不会“在最后一次迭代中阻塞等待未到达的数据”。只要至少传输了一个字节,或者流结束或发生错误,它将立即解除阻塞。它不会尝试填充缓冲区。
      猜你喜欢
      • 2017-02-24
      • 2015-08-21
      • 2021-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 1970-01-01
      • 1970-01-01
      • 2018-12-30
      相关资源
      最近更新 更多