2015-09-06 2 views
4

У меня есть достаточно простой код, используя TcpStream и SslStream вокруг него, считывая сокет по строкам с помощью BufReader. Иногда итератор просто перестает возвращаю какие-либо данные с Ok(0):BufReader :: lines() over TcpStream останавливает итерацию

let mut stream = TcpStream::connect((self.config.host.as_ref(), self.config.port)).unwrap(); 
if self.config.ssl { 
    let context = ssl::SslContext::new(ssl::SslMethod::Tlsv1_2).unwrap(); 
    let mut stream = ssl::SslStream::connect(&context, stream).unwrap(); 
    self.stream = Some(ssl::MaybeSslStream::Ssl(stream)); 
} else { 
    self.stream = Some(ssl::MaybeSslStream::Normal(stream)); 
} 

... 

let read_stream = clone_stream(&self.stream); 

let line_reader = BufReader::new(read_stream); 

for line in line_reader.lines() { 
    match line { 
     Ok(line) => { 
      ... 
     } 
     Err(e) => panic!("line read failed: {}", e), 
    } 
} 
println!("lines out, {:?}", self.stream); 

Цикл просто останавливается случайным образом, насколько я могу видеть, и нет никаких оснований полагать, сокет был закрыт на стороне сервера. Вызов self.stream.as_mut().unwrap().read_to_end(&mut buf) после окончания цикла возвращает Ok(0).

Любые советы о том, как это должно обрабатываться? Я не получаю Err, поэтому я могу предположить, что сокет все еще жив, но потом я ничего не могу прочитать от него. Каково текущее состояние сокета и как я должен продолжить?

PS: Я предоставляю реализацию clone_stream в качестве ссылки, как об этом сообщает комментатор.

fn clone_stream(stream: &Option<ssl::MaybeSslStream<TcpStream>>) -> ssl::MaybeSslStream<TcpStream> { 
    if let &Some(ref s) = stream { 
     match s { 
      &ssl::MaybeSslStream::Ssl(ref s) => ssl::MaybeSslStream::Ssl(s.try_clone().unwrap()), 
      &ssl::MaybeSslStream::Normal(ref s) => ssl::MaybeSslStream::Normal(s.try_clone().unwrap()), 
     } 
    } else { 
     panic!(); 
    } 
} 
+0

* нет причин полагать, что разъем был закрыт на стороне сервера * - можете ли вы доказать это так или иначе? Чтение нулевых байтов в закрытом сокете является нормальным случаем, и это звучит так, как будто у вас есть. – Shepmaster

+1

Просьба попытаться уменьшить ваш тестовый пример и создать [MCVE] (/ help/mcve). Как бы то ни было, мы понятия не имеем, что делает «clone_stream». Кроме того, это * может * быть просто ошибкой в ​​SSL-обертке, поэтому попробуйте удалить условный код и прикрепить его к одному или другому. – Shepmaster

ответ

1

Удивительно, но это был «тайм-аут по умолчанию» на клиенте я предполагаю (гнездо движется в CLOSE_WAIT состоянии).

Я зафиксировал его сначала добавлением:

stream.set_read_timeout(Some(Duration::new(60*5, 0))); 
stream.set_write_timeout(Some(Duration::new(60*5, 0))); 

, что сделало итератора неудачно с ErrorKind::WouldBlock на тайм-аут, после чего я добавил код, чтобы послать пакет пинг по проводам, следующей итерации работали точно так, как ожидается.

Смежные вопросы