我正在尝试在Rust中编写一个非常简单的并发服务器来使用该语言的并发原语及其线程模型。这是我的代码:
use std::io::prelude::*;
use std::io::Result;
use std::net::{TcpListener, TcpStream, Shutdown};
use std::sync::{Arc, Mutex};
use std::thread;
fn handle_client(mut stream: TcpStream) -> Result<()> {
try!(stream.write(b"HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nPong!\r\n"));
// try!(stream.shutdown(Shutdown::Both));
Ok(())
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:1337").unwrap();
// let count = Arc::new(Mutex::new(0));
for stream in listener.incoming() {
match stream {
Ok(stream) => {
// let count = count.clone();
thread::spawn(move || {
let _ = handle_client(stream);
// let mut count = count.lock().unwrap();
// *count += 1;
// println!("{:?}", *count);
});
}
Err(e) => {
println!("Error: {}", e);
}
}
}
drop(listener);
}
当我使用上面列出的程序运行ab -c 100 -n 100 http://127.0.0.1:1337/
时,我几乎立即得到apr_socket_recv: Connection reset by peer (104)
。为什么呢?
当我添加try!(stream.shutdown(Shutdown::Both));
(在上方附近注释掉)时,我不再像以前那样得到apr_socket_recv
错误,但是apachebench给了我结果,说明因异常而导致199个请求失败。为什么?我做错了什么?
Concurrency Level: 100
Time taken for tests: 0.008 seconds
Complete requests: 100
Failed requests: 199
(Connect: 0, Receive: 0, Length: 0, Exceptions: 199)
Total transferred: 500 bytes
答案 0 :(得分:7)
我认为问题在于您没有完全读取从客户端发送的数据,因此客户端永远无法转换为阅读响应。当它尝试写入更多数据时,它会注意到套接字已关闭并失败。
我已经扩充了您的示例,以便在回复之前读取所有HTTP标头,忽略任何请求正文。如果有错误的话,我正在努力解决错误:
use std::io::prelude::*;
use std::io::BufReader;
use std::net::{TcpListener, TcpStream};
use std::thread;
fn handle_client(mut stream: TcpStream) {
// Read all the headers
for header in BufReader::new(&mut stream).lines() {
let header = header.unwrap();
if header == "\r" { break }
}
// Write our response
stream.write_all(b"HTTP/1.0 200 OK\r\n\r\n").unwrap();
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
for stream in listener.incoming() {
let stream = stream.unwrap();
thread::spawn(|| {
handle_client(stream);
});
}
}
这适用于ab -c 50 -n 5000 http://127.0.0.1:8080/
:
Benchmarking 127.0.0.1 (be patient)
Completed 500 requests
Completed 1000 requests
Completed 1500 requests
Completed 2000 requests
Completed 2500 requests
Completed 3000 requests
Completed 3500 requests
Completed 4000 requests
Completed 4500 requests
Completed 5000 requests
Finished 5000 requests
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8080
Document Path: /
Document Length: 0 bytes
Concurrency Level: 50
Time taken for tests: 1.293 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 95000 bytes
HTML transferred: 0 bytes
Requests per second: 3868.22 [#/sec] (mean)
Time per request: 12.926 [ms] (mean)
Time per request: 0.259 [ms] (mean, across all concurrent requests)
Transfer rate: 71.77 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 6 1.7 6 14
Processing: 1 6 1.7 6 14
Waiting: 1 6 1.7 6 14
Total: 5 13 2.6 12 23
Percentage of the requests served within a certain time (ms)
50% 12
66% 13
75% 13
80% 14
90% 17
95% 19
98% 21
99% 22
100% 23 (longest request)
答案 1 :(得分:0)
当值被删除时,套接字将被关闭。
由于您的功能在没有正确关闭TCP流的情况下结束,只需关闭套接字,就会出现Connection reset by peer
错误。完全TCP关闭需要在两个方向上发送多条消息。由于套接字已关闭,这显然不会再发生了。
我的第二个问题没有答案。此外,在stackoverflow上,您应该只针对每个问题提出一个问题。