【发布时间】:2022-01-21 05:16:35
【问题描述】:
注意:删除客户端的关机不会出现错误
// server.rs
use std::io::BufReader;
use std::io::Read;
use std::io::Write;
use std::net::Shutdown;
use std::net::TcpListener;
use std::thread;
fn main() {
let listener = TcpListener::bind("127.0.0.1:4000").unwrap();
for stream in listener.incoming() {
let mut stream = stream.unwrap();
thread::spawn(move || {
let mut reader = BufReader::new(&stream);
let mut buffer = [0; 1024];
let len = reader.read(&mut buffer).unwrap();
// no sleep no error, just simulating a time-consuming operation
thread::sleep(std::time::Duration::from_secs(1));
stream.write_all(&buffer[0..len]).unwrap();
stream.shutdown(Shutdown::Write).unwrap();
});
}
}
// client.rs
use std::io::{Read, Write};
use std::net::TcpStream;
use std::thread;
fn main() {
let mut clients = Vec::new();
for _ in 0..1000 {
clients.push(thread::spawn(move || {
let mut client = TcpStream::connect("127.0.0.1:4000").unwrap();
client.write_all("hello".as_bytes()).unwrap();
// no error if remove the following line
client.shutdown(std::net::Shutdown::Write).unwrap();
let mut buffer = Vec::new();
client.read_to_end(&mut buffer).unwrap();
println!("{}", std::str::from_utf8(&buffer).unwrap());
}));
}
for client in clients.into_iter() {
client.join().unwrap();
}
}
据我了解,关闭写操作会在发送之前的数据后附加FIN,然后对端(服务器)仍然可以继续写数据。但是在这1000个客户端中,出现了一些错误:
// server
<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 107, kind: NotConnected, message: "Transport endpoint is not connected" }', src/bin/server.rs:22:46
// client
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" }', src/bin/client.rs:15:45
在客户端关闭后似乎连接关闭了。
更新1: 我使用了 Wireshark,这是错误的连接之一:
No. Time Source Destination Protocol Length Info
1101 13.738139 127.0.0.1 127.0.0.1 TCP 56 10628 → 4000 [SYN] Seq=0 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
1104 13.738157 127.0.0.1 127.0.0.1 TCP 44 4000 → 10628 [RST, ACK] Seq=409345761 Ack=1 Win=0 Len=0
1234 14.251615 127.0.0.1 127.0.0.1 TCP 56 [TCP Retransmission] [TCP Port numbers reused] 10628 → 4000 [SYN] Seq=0 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
1250 14.251690 127.0.0.1 127.0.0.1 TCP 56 [TCP Port numbers reused] 4000 → 10628 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
1266 14.251726 127.0.0.1 127.0.0.1 TCP 44 10628 → 4000 [ACK] Seq=1 Ack=1 Win=2161152 Len=0
1376 14.251949 127.0.0.1 127.0.0.1 TCP 49 10628 → 4000 [PSH, ACK] Seq=1 Ack=1 Win=2161152 Len=5
1387 14.251970 127.0.0.1 127.0.0.1 TCP 44 4000 → 10628 [ACK] Seq=1 Ack=6 Win=2161152 Len=0
1402 14.251996 127.0.0.1 127.0.0.1 TCP 44 10628 → 4000 [FIN, ACK] Seq=6 Ack=1 Win=2161152 Len=0
1412 14.252013 127.0.0.1 127.0.0.1 TCP 44 4000 → 10628 [ACK] Seq=1 Ack=7 Win=2161152 Len=0
2092 15.261312 127.0.0.1 127.0.0.1 TCP 49 4000 → 10628 [PSH, ACK] Seq=1 Ack=7 Win=2161152 Len=5
2101 15.261384 127.0.0.1 127.0.0.1 TCP 44 10628 → 4000 [RST, ACK] Seq=7 Ack=6 Win=0 Len=0
更新2: 正确连接之一:
No. Time Source Destination Protocol Length Info
162 13.731960 127.0.0.1 127.0.0.1 TCP 56 10927 → 4000 [SYN] Seq=0 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
166 13.731997 127.0.0.1 127.0.0.1 TCP 56 4000 → 10927 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
169 13.732013 127.0.0.1 127.0.0.1 TCP 44 10927 → 4000 [ACK] Seq=1 Ack=1 Win=2161152 Len=0
176 13.732035 127.0.0.1 127.0.0.1 TCP 49 10927 → 4000 [PSH, ACK] Seq=1 Ack=1 Win=2161152 Len=5
181 13.732046 127.0.0.1 127.0.0.1 TCP 44 4000 → 10927 [ACK] Seq=1 Ack=6 Win=2161152 Len=0
187 13.732059 127.0.0.1 127.0.0.1 TCP 44 10927 → 4000 [FIN, ACK] Seq=6 Ack=1 Win=2161152 Len=0
191 13.732074 127.0.0.1 127.0.0.1 TCP 44 4000 → 10927 [ACK] Seq=1 Ack=7 Win=2161152 Len=0
1495 14.746260 127.0.0.1 127.0.0.1 TCP 49 4000 → 10927 [PSH, ACK] Seq=1 Ack=7 Win=2161152 Len=5
1502 14.746369 127.0.0.1 127.0.0.1 TCP 44 10927 → 4000 [ACK] Seq=7 Ack=6 Win=2161152 Len=0
1505 14.746423 127.0.0.1 127.0.0.1 TCP 44 4000 → 10927 [FIN, ACK] Seq=6 Ack=7 Win=2161152 Len=0
1512 14.746529 127.0.0.1 127.0.0.1 TCP 44 10927 → 4000 [ACK] Seq=7 Ack=7 Win=2161152 Len=0
【问题讨论】:
-
“但是在这1000个客户端中,出现了一些错误” - 这是否意味着错误只发生了一次,其他999个连接没有问题?这可以重现吗?
-
它是可重现的。对我来说,这种情况发生在 5% 到 50% 的客户身上。我怀疑它与未接受连接的容量有关(来自 strace 的
listen(3, 128)输出),但还没有一个很好的解释。 -
@kmdreko 是的,它是可重现的。
-
'no sleep no error'........睡眠是为了什么?
-
@MartinJames 只是模拟一个耗时的操作