1

我正在尝试实现用于制作 TCP 服务器的库。

这是一个有问题的非常简化的代码:

#![crate_name="http_server2"]
#![crate_type="lib"]

use std::io::{TcpListener, Listener, Acceptor, TcpStream, IoResult, Reader, Writer};
use std::ops::Fn;
use std::sync::Arc;


pub trait Handler: Sized + Send {
    fn do_it(s: TcpStream) -> IoResult<()>;
}

fn serve(handler: Arc<Handler + Sized>) -> IoResult<()>
{
    let listener = TcpListener::bind("127.0.0.1", 1234);

    for stream in try!(listener.listen()).incoming() {
        let stream = try!(stream);
        let handler = handler.clone();
        spawn(proc() {
            handler.do_it(stream);
        });
    }
    Ok(())
}

编译器完全忽略了我的Handler + Sized. 如果我使用 trait Handler 实现结构并尝试serve使用此结构调用,则有关大小的此类建议也将被忽略(http://is.gd/OWs22i)。

<anon>:13:1: 25:2 error: the trait `core::kinds::Sized` is not implemented for the type `Handler+'static+Sized`
<anon>:13 fn serve(handler: Arc<Handler + Sized>) -> IoResult<()>
<anon>:14 {
<anon>:15     let listener = TcpListener::bind("127.0.0.1", 1234);
<anon>:16 
<anon>:17     for stream in try!(listener.listen()).incoming() {
<anon>:18         let stream = try!(stream);
          ...
<anon>:13:1: 25:2 note: the trait `core::kinds::Sized` must be implemented because it is required by `alloc::arc::Arc`
<anon>:13 fn serve(handler: Arc<Handler + Sized>) -> IoResult<()>
<anon>:14 {
<anon>:15     let listener = TcpListener::bind("127.0.0.1", 1234);
<anon>:16 
<anon>:17     for stream in try!(listener.listen()).incoming() {
<anon>:18         let stream = try!(stream);
          ...
error: aborting due to previous error

我怎样才能用多线程实现一个模板函数来接受不同的处理程序?

4

1 回答 1

3

正如我在上面的评论中所说,

use std::io::{TcpListener, Listener, Acceptor, TcpStream, IoResult, Writer};
use std::sync::Arc;

pub trait Handler: Sized + Send {
    fn do_it(&self, s: TcpStream) -> IoResult<()>;
}

fn serve<T: Handler + Sized + Send + Sync>(handler: Arc<T>) -> IoResult<()> {
    let listener = TcpListener::bind("127.0.0.1", 1234);
    for stream in try!(listener.listen()).incoming() {
        let stream = try!(stream);
        let handler = handler.clone();
        spawn(proc() { 
            let _ = handler.do_it(stream); 
        });
    }
    Ok(())
}

struct Hello {
    x: u32,
}

impl Handler for Hello {
    fn do_it(&self, mut s: TcpStream) -> IoResult<()> { s.write_le_u32(self.x) }
}

fn main() { 
    let s = Arc::new(Hello{x: 123,}); 
    let _ = serve(s); 
}

编译得很好。(游戏围栏)


变化

  1. 拍拍。do_it_&self
  2. serve通过添加具有所需约束的类型参数来实现通用化。
  3. 使for in不丢弃写入impl的结果(删除)。HandlerHellodo_it;
  4. 澄清一下let _ = ...,我们故意丢弃结果。

您将无法在游戏围栏中执行它(application terminated abnormally with signal 31 (Bad system call)),因为游戏围栏禁止 IO(在这种情况下为网络 IO)。不过,它在我的本地盒子上运行良好。

于 2014-10-05T10:10:59.403 回答