我似乎在与std :: io :: TcpStream挣扎.我实际上是尝试与另一个系统打开TCP连接,但下面的代码完全模拟了问题.
我有一个Tcp服务器,只需在打开时将"Hello World"写入TcpStream,然后循环以保持连接打开.
fn main() {
let listener = io::TcpListener::bind("127.0.0.1", 8080);
let mut acceptor = listener.listen();
for stream in acceptor.incoming() {
match stream {
Err(_) => { /* connection failed */ }
Ok(stream) => spawn(proc() {
handle(stream);
})
}
}
drop(acceptor);
}
fn handle(mut stream: io::TcpStream) {
stream.write(b"Hello Connection");
loop {}
}
Run Code Online (Sandbox Code Playgroud)
所有客户端都尝试从连接读取单个字节并打印它.
fn main() {
let mut socket = io::TcpStream::connect("127.0.0.1", 8080).unwrap();
loop {
match socket.read_byte() {
Ok(i) => print!("{}", i),
Err(e) => {
println!("Error: {}", e);
break
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是我的客户端在读取时仍然被阻止,直到我终止服务器或关闭TCP连接.这不是我想要的,我需要打开TCP连接很长一段时间,并在客户端和服务器之间来回发送消息.我在这里误解了什么?我与我正在通信的真实系统有完全相同的问题 - 一旦我终止连接,我才会被解锁.
不幸的是,Rust现在没有任何异步I/O工具.这里有一些尝试,以纠正这种情况,但他们远远没有完成呢.也就是说,希望能够实现真正的异步I/O(提议包括同时选择I/O源和通道,这将允许唤醒通过I/O操作在I/O操作中被阻止的任务.虽然目前尚不清楚如何在所有支持的平台上实现这一点,但是还有很多工作要做,而且就我所知,现在没有什么可用的.
但是,您可以在一定程度上模拟这种超时.这远不是最好的解决方案,但它确实有效.它可能看起来像这样(我的代码库中的简化示例):
let mut socket = UdpSocket::bind(address).unwrap();
let mut buf = [0u8, ..MAX_BUF_LEN];
loop {
socket.set_read_timeout(Some(5000));
match socket.recv_from(buf) {
Ok((amt, src)) => { /* handle successful read */ }
Err(ref e) if e.kind == TimedOut => {} // continue
Err(e) => fail!("error receiving data: {}", e) // bail out
}
// do other work, check exit flags, for example
}
Run Code Online (Sandbox Code Playgroud)
这里recv_from
将返回IoError
与kind
设置为TimedOut
如果没有在5内部几秒钟内插座上的数据recv_from
呼叫.你需要在每次循环迭代之前重置超时,因为它更像是一个"截止日期"而不是超时 - 当它到期时,所有调用都会因超时错误而开始失败.
这绝对不是它应该做的方式,但Rust目前没有提供更好的东西.至少它做了它的工作.
更新
现在尝试基于它创建异步事件循环和网络I/O. 它被称为mio
.对于异步I/O,它可能是一个很好的临时(甚至永久,谁知道)解决方案.
归档时间: |
|
查看次数: |
4946 次 |
最近记录: |