套接字编程read()正在读取我的所有写入()

use*_*819 10 c sockets

我有一个客户端和一个服务器.我的客户端有两个read(),服务器代码中有两个write().服务器在第一次write()上向客户端发送数据,客户端读取并存储到缓冲区但它不会停止读取,它会一直读取服务器的第二次write(),因为在我的客户端我将它设置为在流中读取255(根据我的理解).我把255放了,因为我不知道第一个write()的数据数据有多长.我该如何解决?

客户:

n = read(sockfd,buffer,255);
if (n < 0) 
     error("ERROR reading from socket");
      printf("%s\n",buffer);

 n = read(sockfd,buffer,255);
if (n < 0) 
     error("ERROR reading from socket");
      printf("%s\n",buffer);
Run Code Online (Sandbox Code Playgroud)

服务器:

  n = write(newsockfd,datasize,strlen(datasize));
if (n < 0) error("ERROR writing to socket");

n = write(newsockfd,data,255);
if (n < 0) error("ERROR writing to socket");
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 14

您正在经历的是TCP的工作原理.如果服务器write()在客户端调用之前多次调用read(),则read()可以接收先前写入的所有内容,最多可达到指定的最大缓冲区大小.TCP没有消息边界的概念,就像UDP那样.没有什么不妥.你只需要考虑它,就是这样.

如果您需要知道一条消息的结束位置和下一条消息的开始位置,那么您只需要构建消息框架.有几种不同的方法可以做到这一点.

  1. 在发送实际数据之前发送数据长度,以便客户端知道要读取多少数据,例如:

    服务器:

    int datalen = ...; // # of bytes in data
    int tmp = htonl(datalen);
    n = write(newsockfd, (char*)&tmp, sizeof(tmp));
    if (n < 0) error("ERROR writing to socket");
    n = write(newsockfd, data, datalen);
    if (n < 0) error("ERROR writing to socket");
    
    Run Code Online (Sandbox Code Playgroud)

    客户:

    int buflen;
    n = read(sockfd, (char*)&buflen, sizeof(buflen));
    if (n < 0) error("ERROR reading from socket");
    buflen = ntohl(buflen);
    n = read(sockfd, buffer, buflen);
    if (n < 0) error("ERROR reading from socket");
    else printf("%*.*s\n", n, n, buffer);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用未出现在实际数据中的分隔符包装数据,然后客户端可以继续阅读并查找这些分隔符.使用对数据有意义的任何分隔符(STX/ETX,换行符,特殊保留字符等):

    服务器:

    char delim = '\x2';
    n = write(newsockfd, &delim, 1);
    if (n < 0) error("ERROR writing to socket");
    n = write(newsockfd, data, datalen);
    if (n < 0) error("ERROR writing to socket");
    delim = '\x3';
    n = write(newsockfd, &delim, 1);
    if (n < 0) error("ERROR writing to socket");
    
    Run Code Online (Sandbox Code Playgroud)

    客户:

    char tmp;
    
    do
    {
        n = read(sockfd, &tmp, 1);
        if (n < 0) error("ERROR reading from socket");
    
        if (tmp != '\x2')
            continue;
    
        buflen = 0;
    
        do
        {
            n = read(sockfd, &tmp, 1);
            if (n < 0) error("ERROR reading from socket");
    
            if (tmp == '\x3')
                break;
    
            // TODO: if the buffer's capacity has been reached, either reallocate the buffer with a larger size, or fail the operation...
            buffer[buflen] = tmp;
            ++buflen;
        }
        while (1);
    
        printf("%*.*s\n", buflen, buflen, buffer);
        break;
    }
    while (1);
    
    Run Code Online (Sandbox Code Playgroud)