2015-02-13 9 views
7

Bir iş parçacığım var, bu bir soket listesi tutuyor ve listeyi çaprazlamak istiyorum, okunacak bir şey olup olmadığına bak, eğer öyleyse yap - - Bir sonrakine geç. Sorun, ilk düğümün karşısına gelir gelmez, okumadan bir şey geçene kadar tüm yürütme durdurulur. Ben bir nesne, bir okuma engellemek için gerekiyorsa engeller veri bekleniyor olmadığı hakkında herhangi bir garanti sağlar, ancak vermez docZorla engelleme yok TcpStream ile okuma

itibaren bu işlevi std::io::Read::read(&mut self, buf: &mut [u8]) -> Result<usize>

kullanıyorum ama yapamıyor

tipik olarak bunu bir Err dönüş değeri ile bildirecektir.

kaynağına Kazı, TcpStream Oku uygulaması nihayet

pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { 
    let fd = self.fd(); 
    let dolock = || self.lock_nonblocking(); 
    let doread = |nb| unsafe { 
     let flags = if nb {c::MSG_DONTWAIT} else {0}; 
     libc::recv(fd, 
        buf.as_mut_ptr() as *mut libc::c_void, 
        buf.len() as wrlen, 
        flags) as libc::c_int 
    }; 
    read(fd, self.read_deadline, dolock, doread) 
} 

çağırır Ve

impl Read for TcpStream { 
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } 
} 

olan olmayan engelleme okur üzerinde ben döngüler nerede bulabiliriz read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R)

çağırır veri alınana veya bir hata oluşana kadar.

Engellemeyen bir okumayı TcpStream ile zorlamak için bir yol var mı?

+0

Neden soket başına bir iş parçacığı başlatmıyorsunuz? –

+0

@ker Bu uygulama tahmini 5-30 dakika bağlantı süresi içindir ve yaklaşık 200k eşzamanlı bağlantıyı idare edebilmelidir. Ben iş parçacığı miktarının kötü bir şey olduğu varsayımı altında gidiyorum, ama şu anda bunu hesaplamak için bir yol bulmaya çalışıyorum, bu plan B – nathansizemore

+0

olacaktır. Https gibi AsyncIO kitaplıklarına bakmak isteyebilirsiniz: //github.com/carllerche/mio – Levans

cevap

6

Güncelleme Cevap

Bu unutulmamalıdır

, Rust 1.9.0 itibariyle std::net::TcpStream eklediği işlevsellik:

fn set_nonblocking(&self, nonblocking: bool) -> Result<()>

Orijinal Cevap

yapılamadı TcpStream ile tam olarak al ve IO operasyonları için ayrı bir lib kullanmak istemedim, o kullanmadan önce dosya tanımlayıcısını Non-blocking olarak ayarlayın ve okuma/yazma için bir sistem çağrısı çalıştırın. MIO harika görünüyor olsa bile, kesinlikle en güvenli çözüm, ancak yeni bir IO lib uygulamak yerine daha az iş.

extern "system" { 
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t; 
} 

pub fn new(user: User, stream: TcpStream) -> Socket { 

    // First we need to setup the socket as Non-blocking on POSIX 
    let fd = stream.as_raw_fd(); 
    unsafe { 
     let ret_value = libc::fcntl(fd, 
      libc::consts::os::posix01::F_SETFL, 
      libc::consts::os::extra::O_NONBLOCK); 

     // Ensure we didnt get an error code 
     if ret_value < 0 { 
      panic!("Unable to set fd as non-blocking") 
     } 
    } 

    Socket { 
     user: user, 
     stream: stream 
    } 
} 

pub fn read(&mut self) { 
    let count = 512 as size_t; 
    let mut buffer = [0u8; 512]; 
    let fd = self.stream.as_raw_fd(); 

    let mut num_read = 0 as ssize_t; 
    unsafe { 
     let buf_ptr = buffer.as_mut_ptr(); 
     let void_buf_ptr: *mut c_void = mem::transmute(buf_ptr); 
     num_read = read(fd, void_buf_ptr, count); 
     if num_read > 0 { 
      println!("Read: {}", num_read); 
     } 

     println!("test"); 
    } 
}