Rust: сетевое программирование
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Rust: сетевое программирование
С эхо-сервером, по аналогии, довольно просто...
В 1-м, очень draft приближении, это:
Код: Выделить всё
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
fn handle_client(mut stream: TcpStream) {
let mut buffer = [0; 1024];
loop {
stream.read(&mut buffer).expect("Не удалось получить от клиента");
let request = String::from_utf8_lossy(&buffer[..]);
println!("Получен запрос: {}", request);
stream.write(request.as_bytes()).expect("Не удалось отправить клиенту");
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:53500")
.expect("Не удалось привязаться к адресу");
for stream in listener.incoming() {
match stream {
Ok(stream) => {
std::thread::spawn(move || handle_client(stream));
}
Err(e) => {
eprintln!("Не удалось установить соединение: {}", e);
}
}
}
}
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ rustc echo_serv.rs
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ ls -l echo_serv
-rwxrwxr-x 1 olej olej 4354872 дек 19 22:33 echo_serv
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ file echo_serv
echo_serv: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4f8c3dd8d0a2b1f85f46c17017523d14722dde18, for GNU/Linux 3.2.0, with debug_info, not stripped
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ ldd echo_serv
linux-vdso.so.1 (0x00007ffe04699000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f86c02ab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f86c0083000)
/lib64/ld-linux-x86-64.so.2 (0x00007f86c0355000)
- Вложения
-
- echo_serv.rs
- (865 байт) 9 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Rust: сетевое программирование
Запуск сервера (и дальше обмен с ним):
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ ./echo_serv
Получен запрос: 123 456
Получен запрос: строка
Получен запрос: строка
Получен запрос: строка
thread '<unnamed>' panicked at 'Не удалось отправить клиенту: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }', echo_serv.rs:10:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
...
Код: Выделить всё
olej@R420:~$ telnet 127.0.0.1 53500
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
123 456
123 456
строка
строка
^]
telnet> quit
Connection closed.
Код: Выделить всё
olej@R420:~$ nc 127.0.0.1 53500
qwerty
qwerty
^C
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Rust: сетевое программирование
Более-менее отработаннный, тестированием, эхо-сервер:
Код: Выделить всё
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
fn handle_client(mut stream: TcpStream) {
loop {
let mut buffer = [0; 120];
match stream.read(&mut buffer) {
Err(_) => { //клиент закрыл сокет
return;
}
_ => (),
}
match stream.write(&mut buffer) {
Err(_) => { //клиент закрыл сокет
return;
}
_ => (),
}
}
}
fn main() {
const PORT : &str = "53500";
let listener = match
TcpListener::bind("127.0.0.1:".to_string() + PORT) {
Ok(listener) => listener,
Err(_) => {
println!("серверный порт занят");
return;
}
};
println!("waiting on port {}", PORT);
for stream in listener.incoming() {
println!("waiting on port {}", PORT); // новый клиент
match stream {
Ok(stream) => {
std::thread::spawn(move || handle_client(stream));
}
Err(e) => {
eprintln!("ошибка соединения: {}", e);
}
}
}
}
- Вложения
-
- echo_serv.rs
- (1.08 КБ) 9 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Rust: сетевое программирование
И парный к нему TCP клиент:
Код: Выделить всё
use std::io;
use std::io::prelude::*;
use std::net::TcpStream;
fn main() -> std::io::Result<()> {
let mut stream = match TcpStream::connect("127.0.0.1:53500") {
Ok(stream) => stream,
_ => {
println!("no server available");
return Ok(());
},
};
loop {
print!("> ");
io::stdout().flush()?;
let mut req = String::new();
io::stdin()
.read_line(&mut req)
.expect("ошибка ввода пользователя");
if req.is_empty() { // ^D - завершение работы
println!("");
break;
}
if req.len() == 1 { // Enter - завершение работы
break;
}
match stream.write(&req.as_bytes()) {
Ok(..) => (),
Err(e) => println!("Error: {}", e)
}
let mut buffer = [0; 120]; // буфер чтения
match stream.read(&mut buffer) {
Ok(..) => (),
Err(e) => println!("Error: {}", e),
}
let rep = String::from_utf8_lossy(&buffer[..]);
print!("{}", rep);
}
Ok(())
}
- Вложения
-
- echo_cli.rs
- (1.17 КБ) 9 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Rust: сетевое программирование
Для компиляции отдельных (однофайловых) простых приложений нам нет необходимости использовать такой мощный менеджер проектов языка Rust, под именем cargo, а можно напрямую воспользоваться компилятором rustc, так же входящим в инсталляцию проекта Rust:
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ rustc echo_serv.rs
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ rustc echo_cli.rs
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ ls -l | grep ^-rwx
-rwxrwxr-x 1 olej olej 4311104 дек 21 10:58 echo_cli
-rwxrwxr-x 1 olej olej 4361552 дек 21 10:58 echo_serv
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Rust: сетевое программирование
Тестируем:
И то же самое независимо, средствами утилит Linux:
telnet - с учётом тех артефактов поведения telnet, которые описаны и разрешены вот здесь Python: сетевые приложения:
И на самых разных языках мира:
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ ./echo_serv
waiting on port 53500
waiting on port 53500
waiting on port 53500
waiting on port 53500
waiting on port 53500
...
Код: Выделить всё
olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Rust$ ./echo_cli
> 1 234 567
1 234 567
> русская строка
русская строка
> у
у
> я
я
> х
х
>
Код: Выделить всё
olej@R420:~$ nc 127.0.0.1 53500
1 23 456 7890
1 23 456 7890
русская строка
русская строка
^C
Код: Выделить всё
olej@R420:~$ telnet 127.0.0.1 53500
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
string
string
строка
строка
ещё одна строка
ещё одна строка
русская строка
у
я
х
�
^]
telnet> ^]quit
?Invalid command
telnet> quit
Connection closed.
Код: Выделить всё
olej@R420:~$ socat tcp4:127.0.0.1:53500 STDOUT
नमस ्त े
नमस ्त े
Dobrý den
Dobrý den
لسلام عليكم
لسلام عليكم
今日は
今日は
안녕하세요
안녕하세요
你好
你好
^C
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя