我有一个客户端和一个服务器.我的客户端有两个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);
服务器:
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");
解决方法
您正在经历的是TCP的工作原理.如果服务器在客户端调用read()之前多次调用write(),则read()可以接收先前写入的所有内容,最多可达到指定的最大缓冲区大小. TCP没有消息边界的概念,就像UDP那样.没有什么不妥.你只需要考虑它,就是这样.
如果您需要知道一条消息的结束位置和下一条消息的开始位置,那么您只需要构建消息框架.有几种不同的方法可以做到这一点.
>在发送实际数据之前发送数据长度,以便客户端知道要读取多少数据,例如:
服务器:
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,datalen); if (n < 0) error("ERROR writing to socket");
客户:
int buflen; n = read(sockfd,(char*)&buflen,sizeof(buflen)); if (n < 0) error("ERROR reading from socket"); buflen = ntohl(buflen); n = read(sockfd,buflen); if (n < 0) error("ERROR reading from socket"); else printf("%*.*s\n",n,buffer);
>使用未出现在实际数据中的分隔符包装数据,然后客户端可以继续阅读并查找这些分隔符.使用对数据有意义的任何分隔符(STX / ETX,换行符,特殊保留字符等):
服务器:
char delim = '\x2'; n = write(newsockfd,&delim,1); if (n < 0) error("ERROR writing to socket"); n = write(newsockfd,datalen); if (n < 0) error("ERROR writing to socket"); delim = '\x3'; n = write(newsockfd,1); if (n < 0) error("ERROR writing to socket");
客户:
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,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,buffer); break; } while (1);