Skip to content

Instantly share code, notes, and snippets.

@azyobuzin
Forked from tera3939/Cargo.toml
Created October 28, 2016 04:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azyobuzin/3d263fea8ba9befec6dd550ce568271f to your computer and use it in GitHub Desktop.
Save azyobuzin/3d263fea8ba9befec6dd550ce568271f to your computer and use it in GitHub Desktop.
しんどい
[package]
name = "rustcp_server"
version = "0.1.0"
[dependencies]
lazy_static = "0.2.1"
use std::collections::HashMap;
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
#[macro_use]
extern crate lazy_static;
lazy_static! {
// 各スレッドのTcpStreamをスレッド間で共有する
static ref IDS: RwLock<HashMap<String, Arc<Mutex<TcpStream>>>> = {
let ids = HashMap::new();
RwLock::new(ids)
};
}
fn login(stream: Arc<Mutex<TcpStream>>){
/// IDSにUserIDとTcpStreamを保存する
let banner = b"Input your UserID: ";
let _ = stream.lock().unwrap().write(banner);
let mut id = [0;128];
let res = stream.lock().unwrap().read(&mut id);
match res {
Ok(n) => {
let id = std::str::from_utf8(&id[0..n]).unwrap().to_owned();
{
let mut ids = IDS.write().unwrap();
// UserIDとソケットを結びつけ、Thread間で共有する
// TcpStreamへの参照はこの関数内で死んでしまうので実体を渡したいけど
// cannot move out of borrowed content
ids.insert(id, stream);
}
},
Err(why) => panic!("{:?}", why),
}
}
fn logout(){
/// この関数を呼んだスレッドのTcpStreamをShutdownしてIDSから削除する
println!("insert logout");
}
fn send_all(message: &str){
/// IDSに格納されたすべてのTcpStreamにmessageをwriteする
println!("insert send_all");
}
fn handle_client(stream: TcpStream) {
/// method CRLF value
/// クライアントから送られてきたデータを受信して、methodに対応する関数を呼ぶ
let stream = Arc::new(Mutex::new(stream));
loop{
let mut buffer = [0;128];
let res = stream.lock().unwrap().read(&mut buffer);
match res {
Ok(n) => {
if 0 < n {
// 受信したデータを&str型に変換
let message = std::str::from_utf8(&buffer[0..n]).unwrap().split("\r\n").next().unwrap();
// \r\nで分割してmethodを取り出す
match message {
"LOGIN" => login(stream.clone()),
"LOGOUT" => logout(),
_ => send_all(message),
}
}
},
Err(why) => panic!("{:?}", why),
}
}
}
fn main() {
// ソケットを生成
let listener = TcpListener::bind("127.0.0.1:8000").unwrap();
println!("Start Listening...");
// accept()してるっぽい
for stream in listener.incoming() {
println!("Accepted");
match stream {
// incoming()がOk返したらhandle_clientのスレッドを生成
Ok(stream) => {
thread::spawn(move|| {
handle_client(stream)
});
}
// Errが帰ってきたら頑張る
Err(e) => { println!("Error: {:?}", e); }
}
}
// ソケットを閉じる
drop(listener);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment