[英]UNIX domain socket C++ server can not return data to client
这是我正在使用的简单回显服务器,该服务器将接受来自客户端的请求并返回客户端发送给它的内容。 该程序可以在socat
,但是在使用我自己的客户端时将冻结。
我的旧代码存在的问题是我使用read
而不是read_some
。 read
将阻塞管道,直到它读取一定数量的字节或出现管道异常中断read_some
,而read_some
将一次读取一个块。 更新后的版本使用read_some
读取输入流,并检查程序读取的最后一个字符是否为\\0
,如果为\\0
,则意味着它到达命令的末尾,因此它将回显。 之所以可行,是因为我只传递字符串文字,并且管道中没有二进制数据。
服务器的代码是
using namespace std;
const char* epStr = "/tmp/socketDemo";
int main() {
namespace local = boost::asio::local;
boost::asio::io_service io_service;
::unlink(epStr);
local::stream_protocol::endpoint ep(epStr);
local::stream_protocol::acceptor acceptor(io_service, ep);
while(1) {
local::stream_protocol::socket *socket = new local::stream_protocol::socket(io_service);
acceptor.accept(*socket);
char buf[2048] = {0};
boost::system::error_code error;
size_t len = 0;
while(1) {
len += socket->read_some(boost::asio::buffer(buf + len, 2048 - len));
cout << "read " << len << endl;
if (buf[len] == '\0') {
break;
}
}
cout << "read " << len << " bytes" << endl;
cout << buf << endl;
boost::asio::write(*socket, boost::asio::buffer(buf, len), boost::asio::transfer_all());
}
}
例如,使用socat
命令测试服务器时
echo "12345" | socat - UNIX-CONNECT:/tmp/socketDemo
它将返回所需的结果。
我的客户代码是
const char* epStr = "/tmp/socketDemo";
int main(int argc, const char* argv[]) {
boost::asio::io_service io_service;
boost::asio::local::stream_protocol::endpoint ep(epStr);
boost::asio::local::stream_protocol::socket socket(io_service);
socket.connect(ep);
boost::asio::write(socket, boost::asio::buffer(argv[1], strlen(argv[1])), boost::asio::transfer_all());
char buf[1024] = {0};
size_t len = 0;
while(1) {
len += socket.read_some(boost::asio::buffer(buf + len, 2048 - len));
std::cout << "read " << len << std::endl;
if (buf[len] == '\0') {
break;
}
}
std::cout << "read " << len << " bytes\n";
std::cout << buf << std::endl;
socket.close();
当执行客户端时,起初两者都没有输出,在我杀死了客户端之后,服务器将输出它读取n个字节并得到一个坏管道异常的信息。
这可能是由服务器中的read
功能引起的吗? 如果是这样,是否有一种方法可以让它知道应该读取多少数据,而不必在每个消息的开头发送数据块的大小? 我也想知道为什么socat
可以在此服务器上正常工作? 谢谢!
我也想知道为什么socat可以在此服务器上正常工作?
可能是因为socat关闭了套接字,而您的客户端却没有。
如果是这样,是否有一种方法可以让它知道应该读取多少数据,而不必在每个消息的开头发送数据块的大小?
例如,假设您正在定义/使用包含EOM的协议,则一次读取一个字节,直到读取消息结尾字符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.