TCP/IP网络编程 -- (五)基于 TCP 的服务端/客户端(2)
5.1回声服务器的完美实现
由于上一章末尾提到的问题
write(sock, message, strlen(message));
str_len = read(sock, message, BUF_SIZE - 1);
message[str_len] = 0;
printf("Message from server: %s", message);
- client 多次发送的数据被被一次性传给了 server,于是回传的时候把多条信息一起发过来了
- client 一次发送的数据太长,可能多次 write 才能写完,操作系统把数据分为了多个数据包,client 在没有收完所有数据包的时候就调用了read,于是把一条信息分成了多条打印出来
因此如果可以提前知道 client 一共要收多少字节的数据,就可以等全部收完了再打印
str_len = write(sock, message, strlen(message));
recv_len = 0;
while(recv_len < str_len) {
recv_cnt = read(sock, &message[recv_len], BUF_SIZE - 1);
if (recv_cnt == -1)
error_handling("read() error");
recv_len += recv_cnt;
}
message[str_len] = 0;
printf("Message from server: %s", message);
但这是基于回声服务器的方法,正常情况下客户端并不会事先知道要接收多少数据,因此需要靠应用层协议来解决,即解决粘包问题,例如 HTTP 设置回车符,换行符作为 HTTP header 的边界,用 Content-lenth 字段作为 HTTP body 的边界
《TCP/IP网络编程》中定义了一种简单的应用层协议来解决,思路是固定各类信息的长度,消息长度的信息也再服务器与客户端之间发送
5.2TCP原理
write函数调用后并非立即传输数据,而是将数据移至输出缓冲;
read函数调用后并非立即接受数据,而是将数据移至输入缓冲;
数据在在恰当的时候从字节的输出缓冲传入对方的输入缓冲
这些缓冲I/O的特点为
- I/O缓冲在每个TCP socket 中单独存在
- I/O缓冲在创建 socket 时自动生成
- 即使关闭 socket 也将继续输出缓冲中遗留的数据
- 关闭 socket 将丢失输入缓冲中的数据
TCP是全双工的,一个 socket 会创建如上图所示的两个流
标签:--,缓冲,TCP,read,len,message,recv,服务端 From: https://www.cnblogs.com/hzy717zsy/p/17215672.html