前に作成したTCPサーバーに改良を加える
前に作成したTCPサーバーは,受け取ったデータを表示してくれないので,少し改良を加えて受け取ったデータを表示できるようにしました。
コード
前に作成したコード
mod errors;
mod result;
# [cfg(test)]
mod tests;
use std::io::{Error, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;
pub use self::errors::ServerSessionError;
pub use self::result::ServerSessionResult;
pub struct Server {
addr: Option<String>,
}
impl Server {
pub fn new() -> Result<(Server, Vec<ServerSessionResult>), ServerSessionError> {
let server = Server {
addr: Some("somewhere".to_string()),
};
let mut results = Vec::with_capacity(4);
Ok((server, results))
}
pub fn listen_and_serve(self) {
// Build a server
let listener = TcpListener::bind("127.0.0.1:1935").expect("Error: Failed to bind");
println!("Listening...");
for streams in listener.incoming() {
match streams {
Err(e) => { eprintln!("error: {}", e) },
Ok(stream) => {
thread::spawn(move || {
handler(stream).unwrap_or_else(|error| eprintln!("{:?}", error));
});
}
}
}
}
}
fn handler(mut stream: TcpStream) -> Result<(), Error> {
println!("Connection from {}", stream.peer_addr()?);
let mut buffer = [0; 1024];
loop {
let nbytes = stream.read(&mut buffer)?;
if nbytes == 0 {
return Ok(());
}
stream.write(&buffer[..nbytes])?;
stream.flush()?;
}
}
今回改良を加えたコード
mod errors;
mod result;
# [cfg(test)]
mod tests;
use std::io::{Error, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;
pub use self::errors::ServerSessionError;
pub use self::result::ServerSessionResult;
pub struct Server {
addr: Option<String>,
listener: TcpListener,
}
impl Server {
pub fn new() -> Result<(Server, Vec<ServerSessionResult>), ServerSessionError> {
let server = Server {
addr: Some("somewhere".to_string()),
listener: TcpListener::bind("127.0.0.1:1935").unwrap(),
};
let mut results = Vec::with_capacity(4);
Ok((server, results))
}
pub fn listen_and_serve(&self) {
// Build a server
println!("Listening...");
for streams in self.listener.incoming() {
match streams {
Err(e) => { eprintln!("error: {}", e) },
Ok(stream) => {
thread::spawn(move || {
handler(stream).unwrap_or_else(|error| eprintln!("{:?}", error));
});
}
}
}
}
}
fn handler(mut stream: TcpStream) -> Result<(), Error> {
println!("Connection from {}", stream.peer_addr()?);
let mut buffer = [0; 8192];
loop {
let nbytes = stream.read(&mut buffer)?;
if nbytes == 0 {
return Ok(());
}
for i in 0..nbytes {
print!("{}", buffer[i]);
}
println!("");
// Write buffer to socket
stream.write(&buffer[..nbytes])?;
stream.flush()?;
}
}
改良を加えた点
改良を加えたのはこの部分です。
fn handler(mut stream: TcpStream) -> Result<(), Error> {
println!("Connection from {}", stream.peer_addr()?);
let mut buffer = [0; 8192];
loop {
let nbytes = stream.read(&mut buffer)?;
if nbytes == 0 {
return Ok(());
}
for i in 0..nbytes {
print!("{}", buffer[i]);
}
println!("");
// Write buffer to socket
stream.write(&buffer[..nbytes])?;
stream.flush()?;
}
}
解説
このstream
はソケットのような使い方ができます。
なので,stream.read()
で配列buffer
にクライアントから送信されたデータを読み取ります。
そのとき,bufferの大きさをstream.read()
の戻り値としてnbytes
にとっておきます。
読み取ったデータを出力するには,配列から取り出す必要があるのでforループで0
からnbytes
までの範囲を指定し,buffer
のi番目
の要素をprintln!()
で出力します。(println!()
は改行してしまうので今回は使わないことにしました。)
そして,buffer
の中身をすべて出力し終えたら,println!()
で最後に改行をはさみます。
stream.write()
の部分はエコーサーバーとして機能させるために,ソケットに受け取ったデータをそのまま返しています。なのでstream.flush()
もそのナカマのような感じでついています。
実行結果

pythonのスクリプトで送信した数字を表示できています!