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ます。特性 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

異なるハンドラーを受け入れるマルチスレッドで 1 つのテンプレート関数を実装するにはどうすればよいですか?

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. 書き込みimplの結果Handlerを破棄Hellodo_itないようにします (削除;)。
  4. let _ = ...意図的に結果を破棄することを明確にします。

application terminated abnormally with signal 31 (Bad system call)ただし、プレイペンでは IO (この場合はネットワーク IO) が禁止されているため、プレイペンで実行することはできません ( )。ただし、ローカルボックスでは問題なく動作します。

于 2014-10-05T10:10:59.403 に答える