「 とりあえず チャット・サーバーを作るのを目指そうぜ☆?」
See also: CPerezz/rust-chat-server
cd C:\Users\むずでょ\source\repos\practice-rust
cargo new chat-server-1
config.toml:
[host]
domain = localhost
port = 3000
Cargo.toml ファイルと同じフォルダーに置く。
「 こういうアプリを作るときは 外部ファイルで 設定できるようにしておくと楽だぜ☆」
Cargo.toml:
[dependencies]
serde = "1.0.102"
serde_derive = "1.0.102"
toml = "0.5.5"
main.rs:
// cd C:\Users\むずでょ\source\repos\practice-rust
// cargo new chat-server-1
//
// cd C:\Users\むずでょ\source\repos\practice-rust\chat-server-1
// cargo check
// cargo build
// cargo run
//
// See also:
// https://crates.io/
// #[macro_use]
extern crate serde_derive;
extern crate toml;
mod config;
use config::*;
fn main() {
println!("Hello, world!");
match read_toml("./config.toml".to_string()) {
Ok(config) => {
let host = config.host.unwrap();
println!("Connect | {}:{}", host.domain.unwrap(), host.port.unwrap());
}
Err(err) => panic!(err),
}
}
config.rs:
use serde_derive::*;
use std::fs;
use std::io::{BufReader, Read};
// use toml::*;
#[derive(Debug, Deserialize)]
pub struct Config {
pub host: Option<Host>,
}
#[derive(Debug, Deserialize)]
pub struct Host {
pub domain: Option<String>,
pub port: Option<u16>,
}
pub fn read_toml(path: String) -> Result<Config, toml::de::Error> {
let contents = match read_file(path.to_owned()) {
Ok(s) => s,
Err(e) => panic!("fail to read file: {}", e),
};
println!("contents:\n----\n{}\n----", contents);
toml::from_str(&contents)
}
fn read_file(path: String) -> Result<String, String> {
let mut file_content = String::new();
let mut file_read = fs::File::open(path)
.map(|f| BufReader::new(f))
.map_err(|e| e.to_string())?;
file_read
.read_to_string(&mut file_content)
.map_err(|e| e.to_string())?;
Ok(file_content)
}
Output:
Hello, world!
contents:
----
[host]
domain = "localhost"
port = 3000
----
Connect | localhost:3000
「 デシリアライズするコードを書かないといけないのは イマイチだよな☆」
See also: CPerezz/rust-chat-server
main.rs:
// cd C:\Users\むずでょ\source\repos\practice-rust
// cargo new chat-server-1
//
// cd C:\Users\むずでょ\source\repos\practice-rust\chat-server-1
// cargo check
// cargo build
// cargo run
//
// See also:
// https://crates.io/
// [CPerezz/rust-chat-server](https://github.com/CPerezz/rust-chat-server/blob/master/src/main.rs )
// #[macro_use]
extern crate serde_derive;
extern crate toml;
use std::net::TcpListener;
use std::sync::mpsc;
mod config;
use config::*;
fn main() {
println!("Hello, world!");
match read_toml("./config.toml".to_string()) {
Ok(config) => {
let host = config.host.unwrap();
let host_text = format!("{}:{}", host.domain.unwrap(), host.port.unwrap());
println!("Host | {}", host_text);
//Instanciate the server
let server = TcpListener::bind(&host_text).expect("Listener failet to bind.");
//Set server in Non-blocking state to force it to hear for changes all the time.
server
.set_nonblocking(true)
.expect("Failed to set Non-Blocking state.");
//Generating a clients Storage Vector.
let mut clients: Vec<std::net::TcpStream> = vec![];
//An asynchronous, infinitely buffered channel. The channel function will return a (Sender, Receiver) tuple where all sends will be asynchronous.
//Note that we've specified that Strings will be the types that travel through the channel.
let (sender, reciever) = mpsc::channel::<String>();
}
Err(err) => panic!(err),
}
}
「 localhost:3000 で サーバーが待ってるところまでは こうだが、
次は クライアントが2つ以上接続してくる部分だぜ☆」
「 片方は nngsサーバー、片方は わらちゃん でいいんじゃないの?」
See also: CPerezz/rust-chat-server
main.rs:
// cd C:\Users\むずでょ\source\repos\practice-rust
// cargo new chat-server-1
//
// cd C:\Users\むずでょ\source\repos\practice-rust\chat-server-1
// cargo check
// cargo build
// cargo run
//
// See also:
// https://crates.io/
// [CPerezz/rust-chat-server](https://github.com/CPerezz/rust-chat-server/blob/master/src/main.rs )
// #[macro_use]
extern crate serde_derive;
extern crate toml;
use std::io::{ErrorKind, Read, Write};
use std::net::TcpListener;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
const MSG_SIZE: usize = 32;
mod config;
use config::*;
fn main() {
println!("Hello, world!");
match read_toml("./config.toml".to_string()) {
Ok(config) => {
let host = config.host.unwrap();
let hostText = format!("{}:{}", host.domain.unwrap(), host.port.unwrap());
println!("Host | {}", hostText);
//Instanciate the server
let server = TcpListener::bind(&hostText).expect("Listener failet to bind.");
//Set server in Non-blocking state to force it to hear for changes all the time.
server
.set_nonblocking(true)
.expect("Failed to set Non-Blocking state.");
//Generating a clients Storage Vector.
let mut clients: Vec<std::net::TcpStream> = vec![];
//An asynchronous, infinitely buffered channel. The channel function will return a (Sender, Receiver) tuple where all sends will be asynchronous.
//Note that we've specified that Strings will be the types that travel through the channel.
let (sender, reciever) = mpsc::channel::<String>();
// クライアント待ち受け☆(^~^)
loop {
//If the recieved connection from the listener contains a correct value, is accepted.
if let Ok((mut socket, addr)) = server.accept() {
println!("Client {:?} connected to the chhanel!", addr);
let sender = sender.clone();
//Clone the socket to push it into a thread.
clients.push(socket.try_clone().expect("Failed to clone the client."));
thread::spawn(move || loop {
//Create a buffer to store the msges.
let mut buff = vec![0; MSG_SIZE];
//Hear socket entries from sender an match it with a Result.
match socket.read(&mut buff) {
//a read() syscall on a socket that has been closed on the other end will return 0 bytes read,
//but no error, which should translate to Ok(0) in Rust.
//But this may only apply when the other end closed the connection cleanly.
Ok(0) => {
println!("\nClient: {} left the channel.", addr);
break;
}
//Handle when we do not read an empty socket
Ok(_) => {
//Set the buffer as an Iretartor and take it's elements while the condition retunrs true. Finally returns a Vec of type T
let msg = buff
.clone()
.into_iter()
.take_while(|&x| x != 0)
.collect::<Vec<_>>();
println!("\nMSG as Bytes: {:?}", msg.clone());
let msg = String::from_utf8(msg).expect("Invalid utf8 message");
println!("\n{}: {:?}", addr, msg);
sender.send(msg).expect("failed to send msg to reciever");
}
//Handle reading errors!
Err(ref err) if err.kind() == ErrorKind::WouldBlock => (),
Err(_) => {
println!("\nClient: {} left the channel.", addr);
break;
}
}
thread::sleep(Duration::from_millis(200));
});
}
//A bit of functionall programming to send the message to all the other chat members.
if let Ok(msg) = reciever.try_recv() {
clients = clients
.into_iter()
.filter_map(|mut client| {
let buff = msg.clone().into_bytes();
buff.clone().resize(buff.len(), 0);
client.write_all(&buff).map(|_| client).ok()
})
.collect::<Vec<_>>();
}
thread::sleep(Duration::from_millis(200));
}
}
Err(err) => panic!(err),
}
}
See also: mas-yo/rustgs-testcl
main.rs:
// cd C:\Users\むずでょ\source\repos\practice-rust
// cargo new chat-client-1
//
// cd C:\Users\むずでょ\source\repos\practice-rust\chat-client-1
// cargo check
// cargo build
// cargo run
//
// See also:
// https://crates.io/
// #[macro_use]
extern crate serde_derive;
extern crate toml;
// TcpListener は、標準のと Tokio のとがあって、どちらか選べだぜ☆(^~^)
use std::net::TcpStream;
mod config;
use config::*;
fn main() {
println!("I am a client!");
match read_toml("./config.toml".to_string()) {
Ok(config) => {
let host = config.host.unwrap();
let host_text = format!("{}:{}", host.domain.unwrap(), host.port.unwrap());
println!("Host | {}", host_text);
let client = TcpStream::connect(&host_text)
.and_then(move |stream| Ok(()))
.map_err(|err| {
println!("connection error = {:?}", err);
});
}
Err(err) => panic!(err),
}
}
main.rs
// cd C:\Users\むずでょ\source\repos\practice-rust
// cargo new chat-client-1
//
// cd C:\Users\むずでょ\source\repos\practice-rust\chat-client-1
// cargo check
// cargo build
// cargo run
//
// See also:
// https://crates.io/
// #[macro_use]
extern crate serde_derive;
extern crate toml;
// TcpListener は、標準のと Tokio のとがあって、どちらか選べだぜ☆(^~^)
use std::net::TcpStream;
mod config;
use config::*;
fn main() {
println!("I am a client!");
match read_toml("./config.toml".to_string()) {
Ok(config) => {
let host = config.host.unwrap();
let host_text = format!("{}:{}", host.domain.unwrap(), host.port.unwrap());
println!("Host | {}", host_text);
let client = TcpStream::connect(&host_text)
.and_then(move |stream| {
stream.set_nodelay(true);
println!("connected");
let mut s = String::new();
std::io::stdin().read_line(&mut s).ok();
println!("Input | [{}]", s);
Ok(())
})
.map_err(|err| {
println!("connection error = {:?}", err);
});
}
Err(err) => panic!(err),
}
}
「 これで テキストを一方的に送り付けて終了することができるぜ☆」
「 前に書いたエコー・サーバーは どこに行ったんだろうな☆?」
let mut s = String::new();
std::io::stdin().read_line(&mut s).ok();
「 リード・ラインで 標準入力へのコマンド入力を待機していたら、サーバーからのメッセージを受け取れないだろ☆」
「 サーバーからのメッセージは バックグラウンドに流しておけないの?」
「 じゃあ サーバーからのメッセージは 標準エラー出力にでも流せばいいのかだぜ☆?!」
let client = TcpStream::connect(&host_text)
.and_then(move |stream| {
// use std::io::{BufRead, BufReader, BufWriter, Error, Write};
// Buffering.
let mut reader = BufReader::new(&stream);
let mut writer = BufWriter::new(&stream);
「 ↑読む方向と、書く方向があるだろ☆ 確かRust言語では分けるんだぜ☆」
if let Err(err) = reader.read_line(&mut line) {
// panic!("error during receive a line: {}", err);
println!("Error | {}", err);
}
println!("Read | {}", line);
writer.write(format!("{}\n", msg).as_bytes())?;
writer.flush()?;
「 Rustの非同期処理は今でも tokio を使うのかだぜ☆?」
「 Rust 1.39 は async/await が言語の構文に採用されただけだろ☆
引き続き ライブラリは使うんじゃないか……☆?」
if let Err(err) = reader.read_line(&mut line) {
// panic!("error during receive a line: {}", err);
println!("Error | {}", err);
}
println!("Read | {}", line);
「 ↑ read_line
は一見良さそうだが、メッセージが送られてくるまでずっと待ち続けてしまう☆
タイムアウトしない☆」
「 ↑ mio
か tokio
を使わないと まともな処理も行えなさそうだな☆」
Cargo.toml:
[dependencies]
tokio = { version = "0.2.3", features = ["full"] }
「 ↑ 新しい方法が さっぱり分からん☆ 新しいドキュメントを読もうぜ☆」
//! Hello world server.
//!
//! A simple client that opens a TCP stream, writes "hello world\n", and closes
//! the connection.
//!
//! You can test this out by running:
//!
//! ncat -l 6142
//! nc.exe -l -p 6142 -t -e cmd.exe
//!
//! And then in another terminal run:
//!
//! cargo run --example hello_world
/*
* cd C:\Users\むずでょ\source\repos\practice-rust\tokio
* cargo check --example ep2-created-stream
* cargo build --example ep2-created-stream
* cargo run --example ep2-created-stream
*
* [Hello World!](https://tokio.rs/docs/getting-started/hello-world/)
* [tokio 0.2.3](https://docs.rs/crate/tokio/0.2.3)
*/
use futures::executor::block_on;
use std::net::SocketAddr;
use tokio::net::TcpStream;
async fn connect() {
let addr: SocketAddr = "127.0.0.1:6142".parse().unwrap();
// Connect to port 6142 on localhost
let stream = TcpStream::connect(&addr).await.unwrap();
// Following snippets come here...
println!("Info | Connect end.");
}
fn main() {
block_on(connect());
println!("Info | Finished.");
}
Output:
Info | Finished.
「 ↑ 非同期処理の中の println! って どこに書き出されてんの?」
「 どうも block_on
を さっと抜けて終了してるみたいだぜ☆
スリープ入れて確かめよう……☆」
/*
* cd C:\Users\むずでょ\source\repos\practice-rust\tokio
* cargo check --example ep2-created-stream
* cargo build --example ep2-created-stream
* cargo run --example ep2-created-stream
*
* [Hello World!](https://tokio.rs/docs/getting-started/hello-world/)
* [tokio 0.2.3](https://docs.rs/crate/tokio/0.2.3)
*/
use futures::executor::block_on;
use std::net::SocketAddr;
use tokio::net::TcpStream;
async fn connect() {
// Sleep 3 seconds.
println!("Info | Please wait 3 seconds.");
std::thread::sleep(std::time::Duration::from_secs(3));
println!("Info | Connect end.");
}
fn main() {
println!("Info | Please wait 2 seconds.");
std::thread::sleep(std::time::Duration::from_secs(2));
block_on(connect());
// Sleep 9 seconds.
println!("Info | Please wait 9 seconds.");
std::thread::sleep(std::time::Duration::from_secs(9));
println!("Info | Finished.");
}
Output:
Info | Please wait 2 seconds.
Info | Please wait 3 seconds.
Info | Connect end.
Info | Please wait 9 seconds.
Info | Finished.
match TcpStream::connect(&addr).await {
Ok(_x) => {}
Err(e) => println!("{:?}", e),
};
thread 'main' panicked at 'no current reactor', C:\Users\むずでょ\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.4\src\io\driver\mod.rs:243:21
stack backtrace:
0: backtrace::backtrace::trace_unsynchronized
at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.37\src\backtrace\mod.rs:66
「 ↑エラーになってしまうな☆ カレント・リアクター って何だぜ☆?」
「 block_on( ) で呼び出したのが 相性合ってないんじゃないか☆?」
「 非同期処理で println! とか使ってはいけなかったりするのだろうか☆?」
#[tokio::main]
async fn main() {
block_on(connect()); // syncronized.
// tokio::spawn(connect()); // asyncronized.
//! Hello world server.
//!
//! A simple client that opens a TCP stream, writes "hello world\n", and closes
//! the connection.
//!
//! You can test this out by running:
//!
//! ncat -l 6142
//! nc.exe -l -p 6142 -t -e cmd.exe
//!
//! And then in another terminal run:
//!
//! cargo run --example hello_world
/*
* cd C:\Users\むずでょ\source\repos\practice-rust\tokio
* cargo check --example ep2-created-stream
* cargo build --example ep2-created-stream
* cargo run --example ep2-created-stream
*
* [Hello World!](https://tokio.rs/docs/getting-started/hello-world/)
* [tokio 0.2.3](https://docs.rs/crate/tokio/0.2.3)
*/
use futures::executor::block_on;
use std::net::SocketAddr;
// use tokio::net::TcpStream;
async fn connect() {
// Sleep 3 seconds.
println!("Info | Please wait 1 seconds.");
std::thread::sleep(std::time::Duration::from_secs(1));
let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();
// https://docs.rs/tokio-tcp/0.1.2/src/tokio_tcp/stream.rs.html#49-58
match tokio::net::TcpStream::connect(&addr).await {
Ok(_stream) => {
// Following snippets come here...
println!("Info | Connect end.");
}
Err(e) => println!("{:?}", e),
};
}
#[tokio::main]
async fn main() {
println!("Info | Please wait 1 seconds.");
std::thread::sleep(std::time::Duration::from_secs(1));
// syncronized.
block_on(connect());
// asyncronized.
// tokio::spawn(connect());
// Sleep 9 seconds.
println!("Info | Please wait 3 seconds.");
std::thread::sleep(std::time::Duration::from_secs(3));
println!("Info | Finished.");
}
Output:
Info | Please wait 1 seconds.
Info | Please wait 1 seconds.
Os { code: 10061, kind: ConnectionRefused, message: "対象のコンピューターによって拒否されたため、接続できませんでした。" }
Info | Please wait 3 seconds.
Info | Finished.
「 接続に失敗するところまで 行ったのだった☆
テスト用のエコー・サーバーを用意しよう☆」
// https://docs.rs/tokio-tcp/0.1.2/src/tokio_tcp/stream.rs.html#49-58
match tokio::net::TcpStream::connect(&addr).await {
Ok(_stream) => {
// Following snippets come here...
println!("Info | Connect end.");
}
Err(e) => println!("{:?}", e),
};
Output:
Info | Please wait 1 seconds.
Info | Please wait 1 seconds.
Host | 127.0.0.1:3000
Os { code: 10061, kind: ConnectionRefused, message: "対象のコンピューターによって拒否されたため、接続できませんでした。" }
Info | Please wait 3 seconds.
Info | Finished.
「 こんな短いコードでエラーになってるからな☆ どこが問題なんだろな☆」
「 v4 と v6 が混在してるのかも知らん☆ localhost:3000
を止めて 127.0.0.1:3000
にしよう☆
よし、いけた☆」
use tokio::net::tcp::TcpStream;
use tokio::net::TcpStream;
async fn connect() {
// v4 か v6 かはサーバー側と合わせること。
let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();
println!("Host | {}", &addr);
// クライアント側は リスナーではなく、ストリームを取得する。
// https://docs.rs/tokio-tcp/0.1.2/src/tokio_tcp/stream.rs.html#49-58
match TcpStream::connect(&addr).await {
Ok(mut stream) => {
match stream.set_nodelay(true) {
Ok(_x) => {}
Err(e) => panic!("{}", e),
}
println!("Connected from | {:?}", stream.peer_addr().unwrap());
// Write some data.
match stream.write_all(b"hot dog!").await {
Ok(_x) => {}
Err(e) => panic!("{}", e),
}
stream.flush();
// Sleep 3 seconds.
println!("Info | Please wait 3 seconds.");
std::thread::sleep(std::time::Duration::from_secs(1));
// Read.
let mut buffer = String::new();
stream.read_to_string(&mut buffer);
println!("Read | {:?}", &buffer);
}
Err(e) => println!("{:?}", e),
};
}
「 ↑こう書いても 実行はできるがサーバーからのメッセージは取れないぜ☆」
Output:
contents:
----
[host]
# domain = "localhost"
domain = "127.0.0.1"
port = 3000
----
Host | 127.0.0.1:3000
Server standup | 127.0.0.1:3000
Connection from | 127.0.0.1:51973
Info | Waiting...
Read | hot dog!
Write | poppo
Info | Waiting...
Error | 確立された接続がホスト コンピューターのソウトウェアによって中止されました。 (os error 10053)
Read |
Write | poppo
Os { code: 10053, kind: ConnectionAborted, message: "確立された接続がホスト コンピューターのソウトウェアによって中止されました。" }
match stream.write_all(b"hot dog!").await {
match stream.write_all(b"hot dog!\n").await {
warning: unused `tokio::io::util::read_to_string::ReadToString` that must be used
--> examples\ep4-read.rs:47:13
|
47 | stream.read_to_string(&mut buffer);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
= note: futures do nothing unless you `.await` or poll them
// Read.
let mut buffer = String::new();
match stream.read_to_string(&mut buffer).await {
Ok(x) => {
stream.flush();
println!("Read x | {:?}", x);
}
Err(e) => panic!("{}", e),
}
println!("Read | {:?}", &buffer);
/*
* cd C:\Users\むずでょ\source\repos\practice-rust\tokio
* cargo check --example ep4-read
* cargo build --example ep4-read
* cargo run --example ep4-read
*
* [Reading and Writing Data](https://tokio.rs/docs/io/reading_writing_data/)
*/
use futures::executor::block_on;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::SocketAddr;
use std::str;
use tokio::net::TcpStream;
use tokio::prelude::*;
async fn connect() {
// v4 か v6 かはサーバー側と合わせること。
let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();
println!("Host | {}", &addr);
// クライアント側は リスナーではなく、ストリームを取得する。
// https://docs.rs/tokio-tcp/0.1.2/src/tokio_tcp/stream.rs.html#49-58
match TcpStream::connect(&addr).await {
Ok(mut stream) => {
match stream.set_nodelay(true) {
Ok(_x) => {}
Err(e) => panic!("{}", e),
}
println!("Connected from | {:?}", stream.peer_addr().unwrap());
loop {
// Write some data.
match stream.write_all("hot dog!\n".as_bytes()).await {
Ok(_x) => {
stream.flush();
println!("Info | Writed.");
}
Err(e) => panic!("{}", e),
}
/*
// Sleep 3 seconds.
println!("Info | Please wait 3 seconds.");
std::thread::sleep(std::time::Duration::from_secs(3));
*/
println!("Info | Waiting for read.");
// Read.
// https://docs.rs/tokio/0.1.12/tokio/prelude/trait.Read.html#tymethod.read
let mut buffer = [0; 10];
// read up to 10 bytes
match stream.read(&mut buffer[..]).await {
Ok(size) => {
println!(
"Read | {} | {:?}",
size,
str::from_utf8(&buffer[..size]).unwrap()
);
}
Err(e) => panic!(e),
}
/*
// Sleep 3 seconds.
println!("Info | Please wait 3 seconds.");
std::thread::sleep(std::time::Duration::from_secs(3));
// Write some data.
match stream.write_all("Jump kick!".as_bytes()).await {
Ok(_x) => {
// stream.flush();
println!("Info | Writed.");
}
Err(e) => panic!("{}", e),
}
*/
}
}
Err(e) => println!("{:?}", e),
};
}
#[tokio::main]
async fn main() {
println!("Info | Please wait 1 seconds.");
std::thread::sleep(std::time::Duration::from_secs(1));
// syncronized.
block_on(connect());
// asyncronized.
// tokio::spawn(connect());
// Sleep 9 seconds.
println!("Info | Please wait 10 seconds.");
std::thread::sleep(std::time::Duration::from_secs(10));
println!("Info | Finished.");
}
「 ↑ 改行コードの送受信は分からんなあ☆ 1行ずつかも知らん☆」
「 \n
が送られてくるまで、受信側が待機してしまうのかだぜ☆」
/*
* cd C:\Users\むずでょ\source\repos\practice-rust\tokio
* cargo check --example ep5-input-read
* cargo build --example ep5-input-read
* cargo run --example ep5-input-read
*
* [Reading and Writing Data](https://tokio.rs/docs/io/reading_writing_data/)
*/
use futures::executor::block_on;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::net::SocketAddr;
use std::str;
use tokio::net::TcpStream;
use tokio::prelude::*;
async fn connect() {
// v4 か v6 かはサーバー側と合わせること。
let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();
println!("Host | {}", &addr);
// クライアント側は リスナーではなく、ストリームを取得する。
// https://docs.rs/tokio-tcp/0.1.2/src/tokio_tcp/stream.rs.html#49-58
match TcpStream::connect(&addr).await {
Ok(mut stream) => {
match stream.set_nodelay(true) {
Ok(_x) => {}
Err(e) => panic!("{}", e),
}
println!("Connected from | {:?}", stream.peer_addr().unwrap());
loop {
// 標準入力。
println!("Info | Please key typing.");
let mut line = String::new();
std::io::stdin().read_line(&mut line).ok();
// 改行を削る。
line = line.replace("\r", "\n").replace("\n", "");
println!("Input | [{}]", line);
match line.as_str() {
"exit" => {
// ループから抜けます。このコマンドはサーバー側には送れません。
break;
}
"" => {
// 空打ちで、サーバーのメッセージ読取。
// この状態からは途中で抜けれません。
println!("Info | Waiting for read.");
// Read.
// https://docs.rs/tokio/0.1.12/tokio/prelude/trait.Read.html#tymethod.read
let mut buffer = [0; 2048];
// 末尾の改行をもって受信完了。
match stream.read(&mut buffer[..]).await {
Ok(size) => {
println!(
"Read | {} | {:?}",
size,
str::from_utf8(&buffer[..size]).unwrap()
);
}
Err(e) => panic!(e),
}
}
_ => {
// その他は、サーバーへのメッセージ送信。
println!("Write | {}", line);
// 改行を付けてください。受信側が 受信完了するために必要です。
match stream.write_all(format!("{}\n", line).as_bytes()).await {
Ok(_x) => {
stream.flush();
println!("Info | Writed.");
}
Err(e) => panic!("{}", e),
}
}
}
}
}
Err(e) => println!("{:?}", e),
};
}
#[tokio::main]
async fn main() {
println!("Info | Please wait 1 seconds.");
std::thread::sleep(std::time::Duration::from_secs(1));
// syncronized.
block_on(connect());
// asyncronized.
// tokio::spawn(connect());
// Sleep 9 seconds.
println!("Info | Please wait 10 seconds.");
std::thread::sleep(std::time::Duration::from_secs(10));
println!("Info | Finished.");
}
「 ↑ .await
したら ブロッキングしてしまうじゃないか☆
どうやって ノン・ブロッキングで読み取るんだぜ☆?」
「 Tokio は Non-blocking I/O なはずなんだがなあ☆?」
「 IPアドレスの数を Who is で調べて 入れると接続できたんだが、
Rust言語って名前解決してくれないの☆?」
adminmatch alpha beta b 19 30 0
「 ↑adminmatch
コマンドって自分で打つのかだぜ☆?」
thread 'main' panicked at 'Box<Any>', examples\ep5-input-read.rs:75:47
stack backtrace:
0: backtrace::backtrace::trace_unsynchronized
at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.37\src\backtrace\mod.rs:66
1: std::sys_common::backtrace::_print_fmt
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\sys_common\backtrace.rs:76
2: std::sys_common::backtrace::_print::{{impl}}::fmt
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\sys_common\backtrace.rs:60
3: core::fmt::write
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libcore\fmt\mod.rs:1030
4: std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\io\mod.rs:1412
5: std::sys_common::backtrace::_print
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\sys_common\backtrace.rs:64
6: std::sys_common::backtrace::print
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\sys_common\backtrace.rs:49
7: std::panicking::default_hook::{{closure}}
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\panicking.rs:196
8: std::panicking::default_hook
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\panicking.rs:210
9: std::panicking::rust_panic_with_hook
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\/src\libstd\panicking.rs:473
10: std::panicking::begin_panic<std::io::error::Error>
at /rustc/4560ea788cb760f0a34127156c78e2552949f734\src\libstd\panicking.rs:407
...
<書きかけ>
Crieitは個人で開発中です。
興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!