chore: reorg
This commit is contained in:
5
__network/tcp/README.md
Normal file
5
__network/tcp/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
from:
|
||||
https://riptutorial.com/rust/example/4404/a-simple-tcp-client-and-server-application--echo
|
||||
|
||||
|
||||
5
__network/tcp/tcp_client/Cargo.lock
generated
Normal file
5
__network/tcp/tcp_client/Cargo.lock
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "udp_client"
|
||||
version = "0.1.0"
|
||||
9
__network/tcp/tcp_client/Cargo.toml
Normal file
9
__network/tcp/tcp_client/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "udp_client"
|
||||
version = "0.1.0"
|
||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
28
__network/tcp/tcp_client/src/main.rs
Normal file
28
__network/tcp/tcp_client/src/main.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use std::net::TcpStream;
|
||||
use std::io::{ Read, Write };
|
||||
use std::str::from_utf8;
|
||||
|
||||
fn main() {
|
||||
match TcpStream::connect("localhost:3333") {
|
||||
Ok(mut stream) => {
|
||||
println!("Successfully connected to server in port 3333");
|
||||
|
||||
let msg = b"Hello!";
|
||||
stream.write(msg).unwrap();
|
||||
println!("Sent Hello, awaiting reply...");
|
||||
|
||||
let mut data = [0_u8; 6]; // using 6 byte buffer
|
||||
match stream.read_exact(&mut data) {
|
||||
Ok(_) => if &data == msg {
|
||||
println!("Reply is ok!");
|
||||
} else {
|
||||
let text = from_utf8(&data).unwrap();
|
||||
println!("Unexpected reply: {}", text);
|
||||
},
|
||||
Err(e) => println!("Failed to receive data: {}", e),
|
||||
}
|
||||
},
|
||||
Err(e) => println!("Failed to connect: {}", e),
|
||||
}
|
||||
println!("Terminated.");
|
||||
}
|
||||
5
__network/tcp/tcp_server/Cargo.lock
generated
Normal file
5
__network/tcp/tcp_server/Cargo.lock
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "udp_server"
|
||||
version = "0.1.0"
|
||||
9
__network/tcp/tcp_server/Cargo.toml
Normal file
9
__network/tcp/tcp_server/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "udp_server"
|
||||
version = "0.1.0"
|
||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
39
__network/tcp/tcp_server/src/main.rs
Normal file
39
__network/tcp/tcp_server/src/main.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::thread;
|
||||
use std::net::{ TcpListener, TcpStream, Shutdown };
|
||||
use std::io::{ Read, Write };
|
||||
|
||||
fn handle_client(mut stream: TcpStream) {
|
||||
let mut data = [0_u8; 50]; // using 50 byte buffer
|
||||
while match stream.read(&mut data) {
|
||||
Ok(size) => {
|
||||
// echo everything!
|
||||
stream.write(&data[0..size]).unwrap();
|
||||
true
|
||||
},
|
||||
Err(_) => {
|
||||
println!("An error occurred, terminating connection with {}", stream.peer_addr().unwrap());
|
||||
stream.shutdown(Shutdown::Both).unwrap();
|
||||
false
|
||||
},
|
||||
} {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let listener = TcpListener::bind("0.0.0.0:3333").unwrap();
|
||||
// accept connections and process them, spawning a new thread for each one
|
||||
println!("Server listening on port 3333");
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
println!("New connection: {}", stream.peer_addr().unwrap());
|
||||
thread::spawn(move|| {
|
||||
// connection succeeded
|
||||
handle_client(stream)
|
||||
});
|
||||
},
|
||||
Err(e) => println!("Error: {}", e),
|
||||
}
|
||||
}
|
||||
// close the socket server
|
||||
drop(listener);
|
||||
}
|
||||
5
__network/udp_laminar/README.md
Normal file
5
__network/udp_laminar/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
url:
|
||||
https://github.com/amethyst/laminar
|
||||
|
||||
|
||||
92
__network/udp_laminar/simple_udp.rs
Normal file
92
__network/udp_laminar/simple_udp.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
//! This module provides an simple client, server examples with communication over udp.
|
||||
//! 1. setting up server to receive data.
|
||||
//! 2. setting up client to send data.
|
||||
//! 3. serialize data to send and deserialize when received.
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Instant;
|
||||
|
||||
use bincode::{deserialize, serialize};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use laminar::{Packet, Socket, SocketEvent};
|
||||
|
||||
/// The socket address of where the server is located.
|
||||
const SERVER_ADDR: &'static str = "127.0.0.1:12345";
|
||||
// The client address from where the data is sent.
|
||||
const CLIENT_ADDR: &'static str = "127.0.0.1:12346";
|
||||
|
||||
fn client_address() -> SocketAddr {
|
||||
CLIENT_ADDR.parse().unwrap()
|
||||
}
|
||||
|
||||
fn server_address() -> SocketAddr {
|
||||
SERVER_ADDR.parse().unwrap()
|
||||
}
|
||||
|
||||
/// This will run an simple example with client and server communicating.
|
||||
#[allow(unused_must_use)]
|
||||
pub fn main() {
|
||||
let mut server = Socket::bind(server_address()).unwrap();
|
||||
|
||||
/* setup our `Client` and send some test data. */
|
||||
let mut client = Socket::bind(client_address()).unwrap();
|
||||
|
||||
client.send(Packet::unreliable(
|
||||
server_address(),
|
||||
serialize(&DataType::Coords {
|
||||
latitude: 10.55454,
|
||||
longitude: 10.555,
|
||||
altitude: 1.3,
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
client.send(Packet::unreliable(
|
||||
server_address(),
|
||||
serialize(&DataType::Coords {
|
||||
latitude: 3.344,
|
||||
longitude: 5.4545,
|
||||
altitude: 1.33,
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
client.send(Packet::unreliable(
|
||||
server_address(),
|
||||
serialize(&DataType::Text {
|
||||
string: String::from("Some information"),
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
// Send the queued send operations
|
||||
client.manual_poll(Instant::now());
|
||||
|
||||
// Check for any new packets
|
||||
server.manual_poll(Instant::now());
|
||||
|
||||
// ==== results ====
|
||||
// Coords { longitude: 10.555, latitude: 10.55454, altitude: 1.3 }
|
||||
// Coords { longitude: 5.4545, latitude: 3.344, altitude: 1.33 }
|
||||
// Text { string: "Some information" }
|
||||
while let Some(pkt) = server.recv() {
|
||||
match pkt {
|
||||
SocketEvent::Packet(pkt) => {
|
||||
println!["{:?}", deserialize::<DataType>(pkt.payload()).unwrap()]
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
enum DataType {
|
||||
Coords {
|
||||
longitude: f32,
|
||||
latitude: f32,
|
||||
altitude: f32,
|
||||
},
|
||||
Text {
|
||||
string: String,
|
||||
},
|
||||
}
|
||||
76
__network/udp_laminar/udp.rs
Normal file
76
__network/udp_laminar/udp.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
//! This module provides examples for the UDP api.
|
||||
//! 1. sending data
|
||||
//! 2. receiving data
|
||||
//! 3. constructing the packet for sending.
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use laminar::{Packet, Result, Socket, SocketEvent};
|
||||
|
||||
/// The socket address of where the server is located.
|
||||
const SERVER_ADDR: &'static str = "127.0.0.1:12345";
|
||||
// The client address from where the data is sent.
|
||||
const CLIENT_ADDR: &'static str = "127.0.0.1:12346";
|
||||
|
||||
fn client_address() -> SocketAddr {
|
||||
CLIENT_ADDR.parse().unwrap()
|
||||
}
|
||||
|
||||
fn server_address() -> SocketAddr {
|
||||
SERVER_ADDR.parse().unwrap()
|
||||
}
|
||||
|
||||
/// This is an example of how to send data to an specific address.
|
||||
pub fn send_data() -> Result<()> {
|
||||
// Setup a udp socket and bind it to the client address.
|
||||
let mut socket = Socket::bind(client_address()).unwrap();
|
||||
|
||||
let packet = construct_packet();
|
||||
|
||||
// next send or packet to the endpoint we earlier putted into the packet.
|
||||
socket.send(packet)
|
||||
}
|
||||
|
||||
/// This is an example of how to receive data over udp.
|
||||
pub fn receive_data() {
|
||||
// setup an udp socket and bind it to the client address.
|
||||
let mut socket = Socket::bind(server_address()).unwrap();
|
||||
|
||||
// Next start receiving.
|
||||
loop {
|
||||
if let Some(result) = socket.recv() {
|
||||
match result {
|
||||
SocketEvent::Packet(packet) => {
|
||||
let endpoint: SocketAddr = packet.addr();
|
||||
let received_data: &[u8] = packet.payload();
|
||||
|
||||
// you can here deserialize your bytes into the data you have passed it when sending.
|
||||
|
||||
println!(
|
||||
"Received packet from: {:?} with length {}",
|
||||
endpoint,
|
||||
received_data.len()
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is an example of how to construct a packet.
|
||||
pub fn construct_packet() -> Packet {
|
||||
// this is the destination address of the packet.
|
||||
let destination: SocketAddr = server_address();
|
||||
|
||||
// lets construct some payload (raw data) for or packet.
|
||||
let raw_data = "example data".as_bytes();
|
||||
|
||||
// lets construct or packet by passing in the destination for this packet and the bytes needed to be send..
|
||||
let packet: Packet = Packet::reliable_unordered(destination, raw_data.to_owned());
|
||||
|
||||
packet
|
||||
}
|
||||
|
||||
// TODO: Use functions in example
|
||||
fn main() {}
|
||||
163
__network/udp_laminar/udp_server_client/Cargo.lock
generated
Normal file
163
__network/udp_laminar/udp_server_client/Cargo.lock
generated
Normal file
@@ -0,0 +1,163 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
dependencies = [
|
||||
"build_const",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "laminar"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de96f75f071a80952498ac17613843a2f529188ac053af7d358403aac4e34551"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc",
|
||||
"crossbeam-channel",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rand",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "udp_server_client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"laminar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
11
__network/udp_laminar/udp_server_client/Cargo.toml
Normal file
11
__network/udp_laminar/udp_server_client/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "udp_server_client"
|
||||
version = "0.1.0"
|
||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
laminar = "0.3"
|
||||
|
||||
109
__network/udp_laminar/udp_server_client/src/main.rs
Normal file
109
__network/udp_laminar/udp_server_client/src/main.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
//! Note that the terms "client" and "server" here are purely what we logically associate with them.
|
||||
//! Technically, they both work the same.
|
||||
//! Note that in practice you don't want to implement a chat client using UDP.
|
||||
use std::io::stdin;
|
||||
use std::thread;
|
||||
use std::time::Instant;
|
||||
|
||||
use laminar::{ErrorKind, Packet, Socket, SocketEvent};
|
||||
|
||||
const SERVER: &str = "127.0.0.1:12351";
|
||||
|
||||
fn server() -> Result<(), ErrorKind> {
|
||||
let mut socket = Socket::bind(SERVER)?;
|
||||
let (sender, receiver) = (socket.get_packet_sender(), socket.get_event_receiver());
|
||||
let _thread = thread::spawn(move || socket.start_polling());
|
||||
|
||||
loop {
|
||||
if let Ok(event) = receiver.recv() {
|
||||
match event {
|
||||
SocketEvent::Packet(packet) => {
|
||||
let msg = packet.payload();
|
||||
|
||||
if msg == b"Bye!" {
|
||||
break;
|
||||
}
|
||||
|
||||
let msg = String::from_utf8_lossy(msg);
|
||||
let ip = packet.addr().ip();
|
||||
|
||||
println!("Received {:?} from {:?}", msg, ip);
|
||||
|
||||
sender
|
||||
.send(Packet::reliable_unordered(
|
||||
packet.addr(),
|
||||
"Copy that!".as_bytes().to_vec(),
|
||||
))
|
||||
.expect("This should send");
|
||||
}
|
||||
SocketEvent::Timeout(address) => {
|
||||
println!("Client timed out: {}", address);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn client() -> Result<(), ErrorKind> {
|
||||
let addr = "127.0.0.1:12352";
|
||||
let mut socket = Socket::bind(addr)?;
|
||||
println!("Connected on {}", addr);
|
||||
|
||||
let server = SERVER.parse().unwrap();
|
||||
|
||||
println!("Type a message and press Enter to send. Send `Bye!` to quit.");
|
||||
|
||||
let stdin = stdin();
|
||||
let mut s_buffer = String::new();
|
||||
|
||||
loop {
|
||||
s_buffer.clear();
|
||||
stdin.read_line(&mut s_buffer)?;
|
||||
let line = s_buffer.replace(|x| x == '\n' || x == '\r', "");
|
||||
|
||||
socket.send(Packet::reliable_unordered(
|
||||
server,
|
||||
line.clone().into_bytes(),
|
||||
))?;
|
||||
|
||||
socket.manual_poll(Instant::now());
|
||||
|
||||
if line == "Bye!" {
|
||||
break;
|
||||
}
|
||||
|
||||
match socket.recv() {
|
||||
Some(SocketEvent::Packet(packet)) => {
|
||||
if packet.addr() == server {
|
||||
println!("Server sent: {}", String::from_utf8_lossy(packet.payload()));
|
||||
} else {
|
||||
println!("Unknown sender.");
|
||||
}
|
||||
}
|
||||
Some(SocketEvent::Timeout(_)) => {}
|
||||
_ => println!("Silence.."),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), ErrorKind> {
|
||||
let stdin = stdin();
|
||||
|
||||
println!("Please type in `server` or `client`.");
|
||||
|
||||
let mut s = String::new();
|
||||
stdin.read_line(&mut s)?;
|
||||
|
||||
if s.starts_with("s") {
|
||||
println!("Starting server..");
|
||||
server()
|
||||
} else {
|
||||
println!("Starting client..");
|
||||
client()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user