我正在Rust中使用事件驱动的服务器,并希望它能够将其连接到尽可能多的客户端。
但是我最多只能同时连接700个客户端并发送数据。如果我尝试增加客户端,则来自客户端的客户端连接开始断开。我正在使用线程创建多个客户端,它开始出现以下错误:
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value:
Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" }',
src/libcore/result.rs
如果禁用了数据发送,则它可以连接1017个客户端,并且可以通过允许进程打开大于1024个的文件来增加数据发送。
我检查了最高在我的操作系统中无法创建的线程数为62096。服务器程序的内存使用量也约为15KB。
我尝试将事件循环容量增加到20,480,尽管它不支持800个客户端。
Server.rs:
extern crate mio;
use mio::net::{TcpListener, TcpStream};
use mio::*;
use mio::{Poll, PollOpt, Ready, Token};
use std::collections::HashMap;
use std::env;
use std::io::{Error, Read, Write};
fn process_events(
e: Event,
listener: &TcpListener,
poll: &Poll,
clients: &mut HashMap<Token, TcpStream>,
mut count: usize,
) {
if e.token() == Token(0) {
match listener.accept() {
Ok((mut stream, addr)) => {
let new_token = Token(count);
println!("new token {:?}", new_token);
poll.register(
&stream,
new_token,
Ready::readable(),
PollOpt::edge() | PollOpt::oneshot(),
)
.unwrap();
println!("Got a client: {:?}", stream.peer_addr().unwrap());
clients.insert(new_token, stream);
}
Err(e) => panic!("Error during connection{}", e),
}
}
if e.token() != Token(0) && e.readiness().is_readable() {
let mut buf = [0; 512];
let mut t = e.token();
let reader = clients.get_mut(&e.token()).unwrap().read(&mut buf);
match reader {
Ok(_) => {
let bytes_no = reader.unwrap();
println!("No of bytes read : {:?}, {:?}", bytes_no, e.token());
}
Err(e) => {
println!("could not read: {}", e);
}
}
poll.reregister(
&clients[&e.token()],
e.token(),
Ready::readable(),
PollOpt::edge() | PollOpt::oneshot(),
)
.unwrap();
}
}
fn main() {
const server: Token = Token(0);
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Provide the argument");
std::process::exit(1);
}
let listen = &args[1];
let addr = listen.parse().unwrap();
let mut listener = TcpListener::bind(&addr).expect("Could not bind");
println!("Server listening on : {}", addr);
let mut clients = HashMap::new();
let mut eve = Events::with_capacity(20480);
let poll = Poll::new().unwrap();
let mut count = 1;
poll.register(
&listener,
server,
Ready::readable(),
PollOpt::edge() | PollOpt::oneshot(),
)
.unwrap();
loop {
poll.poll(&mut eve, None);
for e in &eve {
process_events(e, &listener, &poll, &mut clients, count);
if e.token() == Token(0) {
count += 1;
}
}
poll.reregister(
&listener,
server,
Ready::readable(),
PollOpt::edge() | PollOpt::oneshot(),
)
.unwrap();
}
}
Client.rs:
use std::io;
use std::io::Write;
use std::net::TcpStream;
use std::thread;
fn handle_client() {
let server_addr = String::from("localhost:3000");
if let Ok(mut stream) = TcpStream::connect(server_addr) {
println!("Connected to server {} ", c);
let msg = [0u8; 512];
loop {
stream.write(&msg).unwrap();
}
} else {
println!("could not connect");
}
}
fn main() {
for _i in 0..10000 {
thread::spawn(move || handle_client());
}
}
由于事件驱动的方法比多线程服务器更好,因此预期的客户端应该超过1020。