使用 tokio 根据文档写一个收发字符串内容的tcp server.
文档地址:https://tokio.rs/docs/getting-started/simple-server/
#[macro_use]
extern crate log;
extern crate bytes;
extern crate tokio_io;
extern crate tokio_core;
extern crate tokio_proto;
extern crate tokio_service;
extern crate byteorder;
extern crate futures;
use std::io;
use std::str;
use std::io::Cursor;
use bytes::{BytesMut,BufMut};
use tokio_io::codec::*;
use byteorder::*;
use tokio_proto::TcpServer;
use tokio_proto::pipeline::ServerProto;
//use tokio_proto::multiplex::ServerProto;
//use tokio_proto::streaming::pipeline::ServerProto;
use tokio_io::*;
use tokio_io::codec::Framed;
use tokio_service::Service;
use futures::{future,Future,BoxFuture};
#[test]
fn hello(){
info!("hello");
pub struct MessageCodec;
impl Decoder for MessageCodec{
type Item=String;
type Error=io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error>{
println!("decode:{}",buf.len());
if buf.len()<=4 {
return Ok(None);
}
let len=BigEndian::read_i32(buf.split_to(4).as_ref()) as usize;
let b=buf.split_to(len);
let content=str::from_utf8(b.as_ref());
println!("decode 2:{}",buf.len());
return Ok( Some( content.unwrap().to_owned() ));
}
}
impl Encoder for MessageCodec{
type Item=String;
type Error=io::Error;
fn encode(&mut self, item: String, buf: &mut BytesMut)
-> Result<(), Self::Error>{
println!("encode:{}",item);
buf.put_i32::<BigEndian>(item.len() as i32 );
buf.put_slice(item.into_bytes().as_ref());
return Ok(());
}
}
pub struct MessageProto;
impl<T:AsyncRead+AsyncWrite+'static> ServerProto<T> for MessageProto{
type Request=String;
type Response=String;
type Transport=Framed<T,MessageCodec>;
type BindTransport = Result<Self::Transport,io::Error>;
fn bind_transport(&self, io: T) -> Self::BindTransport{
Ok(io.framed(MessageCodec))
}
}
pub struct GameServer;
impl Service for GameServer{
/// Requests handled by the service.
type Request=String;
/// Responses given by the service.
type Response=String;
/// Errors produced by the service.
type Error=io::Error;
/// The future response value.
type Future=BoxFuture<Self::Response,Self::Error >;
/// Process the request and return the response asynchronously.
fn call(&self, req: Self::Request) -> Self::Future{
println!("receive:{}",req);
return future::ok(req.chars().rev().collect()).boxed();
}
}
let addr="0.0.0.0:9999".parse().unwrap();
let server=TcpServer::new(MessageProto,addr);
println!("start running");
server.serve(|| Ok(GameServer));
println!("hello test");
}
第一次基础上算正规的边看文档,边写,边理解语法,边google。
过程中掌握以下知识点:
1、类型转换
i32 转为 u32
a as u32
2、从 [u8] 中读取一个基础类型
BigEndian::read_i32(buf)
3、byte[] 转为字符串
str::from_utf8([u8])
4、字符串转为bytes
str.into_bytes()
5、slice目前ide无法做到智能语法提示。
需要自己来处理。
6、bytes取一个slice再转为byte[]
buf[a..b].as_ref()
下一步就是自己用tcpstream去连上。
近期评论