首页 > 解决方案 > TCPStream 如何知道消息何时完成?

问题描述

据我了解,TCPStream不知道何时从客户端收到完整的消息,但信息以字节流的形式到达。

但是,当我在 Rust 中执行标准的“Hello World”TCPStream示例时,我正在从流中读取完整的 HTTP 消息。当我发送两条或更多条消息时,它们将相应地分开。

这怎么可能?

use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;

fn main() {
    let listener = TcpListener::bind("127.0.0.1:8080").unwrap();

    for stream in listener.incoming() {
        let stream = stream.unwrap();
        handle_connection(stream);
    }
}

fn handle_connection(mut stream: TcpStream) {
    let mut buffer = [0; 512];
    stream.read(&mut buffer).unwrap();
    println!("{}", String::from_utf8_lossy(&buffer[..]));
}

当我减小缓冲区大小时,HTTP 消息会被剪切,更新的消息会从头开始。我会以某种方式假设我必须自己管理结束和开始一条新的 HTTP 消息?

标签: tcprust

解决方案


在非常低的级别上,客户端使用基本的 Unixwrite(socket, buf, nbytes)操作将字节放入套接字,而服务器则使用nread = read(socket, buf, maxbytes)从套接字中提取字节。

read()write()与套接字一起使用时,它们不保证任何关于将 a 拆分write()为多个read()s 或将多个 s 合并write()为一个 big的行为read()。任何事情都可能发生,只要客户端写入的字节最终将由服务器按照客户端写入它们的顺序读取(假设网络连接由于某种原因没有断开)。

在您的特定情况下,客户端可能发出了两个write()调用,这些调用在 TCP 层中被转换为两个相应的数据包。服务器进程正在等待read()呼叫。服务器操作系统设法唤醒服务器进程,并在第二个数据包到达之前将第一个数据包的内容提供给它,或者以其他方式通过服务器操作系统。因此,服务器进程发现自己处于一个方便的位置,可以处理一个完整的 HTTP 请求。


推荐阅读