我有一个打开并侦听Unix域套接字的测试。套接字被打开并且没有问题地读取数据,但它没有正常关闭。
这是我第二次尝试运行测试时遇到的错误:
主题'test_1'对
Result::unwrap()
上名为Err
的'RUST_BACKTRACE=1
感到恐慌 值:错误{repr:Os {代码:48,消息:“地址已在使用中” }}',.. / src / libcore / result.rs:799注意:使用use std::io::prelude::*; use std::thread; use std::net::Shutdown; use std::os::unix::net::{UnixStream, UnixListener};
运行 回溯。
代码可用at the Rust playground,并且有Github Gist for it。
#[test]
fn test_1() {
driver();
assert_eq!("1", "2");
}
测试用例:
fn driver() {
let listener = UnixListener::bind("/tmp/my_socket.sock").unwrap();
thread::spawn(|| socket_server(listener));
// send a message
busy_work(3);
// try to disconnect the socket
let drop_stream = UnixStream::connect("/tmp/my_socket.sock").unwrap();
let _ = drop_stream.shutdown(Shutdown::Both);
}
主要入口点功能
#[allow(unused_variables)]
fn busy_work(threads: i32) {
// Make a vector to hold the children which are spawned.
let mut children = vec![];
for i in 0..threads {
// Spin up another thread
children.push(thread::spawn(|| socket_client()));
}
for child in children {
// Wait for the thread to finish. Returns a result.
let _ = child.join();
}
}
fn socket_client() {
let mut stream = UnixStream::connect("/tmp/my_socket.sock").unwrap();
stream.write_all(b"hello world").unwrap();
}
按间隔发送数据的功能
fn handle_client(mut stream: UnixStream) {
let mut response = String::new();
stream.read_to_string(&mut response).unwrap();
println!("got response: {:?}", response);
}
处理数据的功能
#[allow(unused_variables)]
fn socket_server(listener: UnixListener) {
// accept connections and process them, spawning a new thread for each one
for stream in listener.incoming() {
match stream {
Ok(mut stream) => {
/* connection succeeded */
let mut response = String::new();
stream.read_to_string(&mut response).unwrap();
if response.is_empty() {
break;
} else {
thread::spawn(|| handle_client(stream));
}
}
Err(err) => {
/* connection failed */
break;
}
}
}
println!("Breaking out of socket_server()");
drop(listener);
}
侦听传入消息的服务器套接字
function CodSubmitOrder(){ $('#btn_cod').attr('disabled', true).addClass('disabled');
$.post('<?php echo base_url('/cod/process-payment');?>', function(data)
{
if(data.errors != undefined)
{
console.log('data error');
var error = '<div class="alert alert-danger">';
$.each(data.errors, function(index, value)
{
error += '<p>'+value+'</p>';
});
error += '</div>';
$.gumboTray(error);
$('#btn_cod').attr('disabled', false).addClass('disabled');
}
else
{
console.log('data success');
if(data.orderId != undefined)
{
window.location = '<?php echo site_url('order-complete/');?>/'+data.orderId;
}
}
console.log(data);
}, 'json');}
答案 0 :(得分:4)
请学习创建Minimal, Complete, and Verifiable example,然后花点时间这样做。在这种情况下,不需要线程或函数或测试框架;运行整个程序两次重现错误:
use std::os::unix::net::UnixListener;
fn main() {
UnixListener::bind("/tmp/my_socket.sock").unwrap();
}
如果您在测试之前和之后查看文件系统,您将看到文件/tmp/my_socket.sock
在第一次运行之前不存在,并且在第二次运行之前存在。删除文件允许程序再次运行完成(此时它会重新创建文件)。
此问题为not unique to Rust:
请注意,一旦创建,即使服务器退出,此套接字文件仍将继续存在。如果服务器随后重新启动,则该文件会阻止重新绑定:
[...]
因此,服务器应在绑定之前取消套接字路径名的链接。
你可以选择在套接字周围添加一些包装器,当它被删除或create a temporary directory that is cleaned when it is dropped时会自动将其删除,但我不确定它的效果如何。您还可以创建一个包装函数,在打开套接字之前删除该文件。