这是我正在处理的简单回显服务器,服务器将接受来自客户端的请求并返回客户端发送给它的内容。该程序可以正常工作socat
,但在使用我自己的客户端时会冻结。
我的旧代码的问题是我使用read
而不是read_some
. read
将阻塞管道,直到它读取一定数量的字节或获得损坏的管道异常,而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
可以毫无问题地使用此服务器?谢谢!