这是一个简易的聊天程序demo,有三个部分组成,服务端,客户端,显示端
服务端,接受任意客户端和显示端的连接,并将每条来自某个客户端的消息广播给所有已经建立连接的客户端
客户端,一个只负责发送消息的程序
显示端,由于cmd输入文本会影响服务端 消息的正常显示,所以单独切分出一个客户端,只负责接收显示消息
简单说下怎么用。先在任意电脑上启动服务端,然后任意电脑上的客户端、显示端可以输入服务端的内网IP地址去建立连接
现在内网环境下的服务端端口是写死的,可以调整之后,出现一个电脑上存在多个服务端
目前存在的问题如下:客户端关掉窗口,还没写正常的shutdown关闭,服务端不会知道,所以clients会越来越大
效果图如下
服务端代码:
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let ip_address = local_ip_address::local_ip().expect("");
let tcp_listener = TcpListener::bind(ip_address.to_string() + ":7777").expect("");
let clients = Arc::new(Mutex::new(Vec::new()));
for stream in tcp_listener.incoming() {
let clients_clone = Arc::clone(&clients);
let mut stream = stream.unwrap();
let peer_addr = stream.peer_addr().expect("");
clients_clone.lock().unwrap().push(stream.try_clone().unwrap());
println!("客户端{:?}建立连接,当前连接的客户端为 {}", peer_addr, clients_clone.lock().unwrap().len());
let clients_clone = Arc::clone(&clients);
thread::spawn(move || {
loop {
let mut buf = [0; 1024];
match stream.read(&mut buf) {
Ok(0) => {
clients_clone.lock().unwrap().retain(|c| c.peer_addr().unwrap() != peer_addr);
println!("客户端{}关闭连接,剩余连接客户端为 {}", peer_addr, clients_clone.lock().unwrap().len());
break;
}
Ok(n) => {
let my_text = String::from_utf8_lossy(&buf[0..n]).to_string();
let mut clients = clients_clone.lock().unwrap();
for client in clients.iter_mut() {
let client_addr = client.peer_addr().expect("");
let text = format!("{} ---> {}", peer_addr, my_text);
if let Err(e) = client.write_all(text.as_bytes()) {
println!("客户端{}写入数据失败: {:?}", client_addr, e);
}
}
}
Err(e) => {
println!("客户端{}读取数据失败: {:?}", peer_addr, e);
break;
}
}
}
});
}
}
客户端代码:
use std::io::{Read, stdin, Write};
use std::net::TcpStream;
fn main() {
println!("请输入目标连接的IP地址");
let mut string = String::new();
stdin().read_line(&mut string).expect("");
let mut tcp_stream = TcpStream::connect(string.trim().to_string() + ":7777").expect("");
println!("成功建立与服务器的连接");
loop {
let mut string = String::new();
stdin().read_line(&mut string).expect("");
tcp_stream.write(string.as_bytes()).expect("");
}
}
显示端代码:
use std::io::{Read, stdin};
use std::net::TcpStream;
fn main() {
println!("请输入目标连接的IP地址");
let mut string = String::new();
stdin().read_line(&mut string).expect("");
let mut tcp_stream = TcpStream::connect(string.trim().to_string() + ":7777").expect("");
println!("建立连接");
loop {
let mut buf = [0; 1024];
tcp_stream.read(&mut buf).expect("");
println!("{}", String::from_utf8_lossy(&buf).replace("\n", "").replace("\0", "").replace("\r", ""));
}
}