├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── main.rs ├── tcp_client.rs ├── udp_client.rs └── udp_server.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | tcp_client 4 | udp_client 5 | udp_server 6 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "rust-network" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-network" 3 | version = "0.1.0" 4 | authors = ["teruya"] 5 | edition = "2018" 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Teruya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socket-programming 2 | 3 | Echo server and client for TCP/UDP with Rust. 4 | 5 | # How to use 6 | 7 | ``` 8 | $ cargo run [tcp|udp] [server|client] [addr:port] 9 | ``` 10 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write, Error}; 2 | use std::net::{TcpListener, TcpStream}; 3 | use std::{thread, str}; 4 | 5 | fn handler(mut stream: TcpStream) -> Result<(), Error> { 6 | println!("My addr is {}", stream.local_addr()?); 7 | println!("Handling data from {}", stream.peer_addr()?); 8 | let mut buffer = [0u8; 1024]; 9 | loop { 10 | let nbytes = stream.read(&mut buffer)?; 11 | if nbytes == 0 { 12 | return Ok(()); 13 | } 14 | print!("{}", str::from_utf8(&buffer[..nbytes]).expect("failed to read")); 15 | stream.write(&buffer[..nbytes])?; 16 | stream.flush()?; 17 | } 18 | } 19 | 20 | fn main() { 21 | let listener = TcpListener::bind("0.0.0.0:33333").expect("Error. failed to bind to the address"); 22 | for streams in listener.incoming() { 23 | match streams { 24 | Err(e) => { eprintln!("error: {}", e)}, 25 | Ok(stream) => { 26 | thread::spawn(move || { 27 | handler(stream).unwrap_or_else(|error| eprintln!("{:?}", error)); 28 | }); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/tcp_client.rs: -------------------------------------------------------------------------------- 1 | use std::net::TcpStream; 2 | use std::{str, env}; 3 | use std::time::Duration; 4 | use std::io::{self, BufRead, BufReader, Write}; 5 | 6 | fn main() { 7 | let args: Vec = env::args().collect(); 8 | if args.len() != 2 { 9 | eprintln!("Please specify address and port. Usage: ./main [address]:[port]"); 10 | std::process::exit(1); 11 | } 12 | let remote = args[1].parse().expect("Usage: ./main [address]:[port]"); 13 | 14 | let mut stream = TcpStream::connect_timeout(&remote, Duration::from_secs(1)).expect("Could not connect."); 15 | stream.set_read_timeout(Some(Duration::from_secs(2))).unwrap(); 16 | stream.set_write_timeout(Some(Duration::from_secs(2))).unwrap(); 17 | 18 | loop { 19 | let mut input = String::new(); 20 | io::stdin().read_line(&mut input).unwrap(); 21 | stream.write(input.as_bytes()).expect("failed to write"); 22 | 23 | let mut reader = BufReader::new(&stream); 24 | let mut buffer = Vec::new(); 25 | reader.read_until(b'\n', &mut buffer).expect("failed to read from the socket"); 26 | print!("{}", str::from_utf8(&buffer).expect("failed to convert to a String")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/udp_client.rs: -------------------------------------------------------------------------------- 1 | use std::net::{UdpSocket, SocketAddr}; 2 | use std::{str, io, env}; 3 | use std::time::Duration; 4 | 5 | fn main() { 6 | let args: Vec = env::args().collect(); 7 | if args.len() != 2 { 8 | eprintln!("please specify target address and port. Usage: ./main [address]:[port]"); 9 | std::process::exit(1); 10 | } 11 | let remote: SocketAddr = args[1].parse().expect("Usage: ./main [address]:[port]"); 12 | 13 | let socket = UdpSocket::bind("127.0.0.1:0").expect("failed to bind socket"); 14 | socket.set_read_timeout(Some(Duration::from_secs(2))).unwrap(); 15 | socket.set_write_timeout(Some(Duration::from_secs(2))).unwrap(); 16 | 17 | loop { 18 | let mut input = String::new(); 19 | io::stdin().read_line(&mut input).unwrap(); 20 | 21 | socket.send_to(input.as_bytes(), &remote).expect("failed to send data"); 22 | 23 | let mut buffer = [0u8; 1024]; 24 | socket.recv_from(&mut buffer).expect("failed to receive"); 25 | print!("{}", str::from_utf8(&buffer).expect("failed to convert to String")); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/udp_server.rs: -------------------------------------------------------------------------------- 1 | use std::net::UdpSocket; 2 | use std::str; 3 | 4 | fn main() { 5 | let server_socket = UdpSocket::bind("127.0.0.1:12345") 6 | .expect("Failed to bind socket"); 7 | loop { 8 | let mut buf = [0u8; 1024]; 9 | match server_socket.recv_from(&mut buf) { 10 | Ok((size, src)) => { 11 | println!("handling data from {}", src); 12 | print!("{}", str::from_utf8(&buf[..size]).expect("Failed to read")); 13 | server_socket.send_to(&buf[..size], src).expect("Failed to send response"); 14 | }, 15 | Err(e) => { 16 | eprintln!("could not recieve a datagram: {}", e); 17 | } 18 | } 19 | } 20 | } 21 | --------------------------------------------------------------------------------