UNIX域套接字
Asio 为 UNIX 域套接字(也称为本地套接字)提供基本支持。 最简单的用法是创建一对连接的套接字。 以下代码会创建一对面向流的套接字:
local::stream_protocol::socket socket1(my_io_context);
local::stream_protocol::socket socket2(my_io_context);
local::connect_pair(socket1, socket2);
要创建面向报文的套接字,使用:
local::datagram_protocol::socket socket1(my_io_context);
local::datagram_protocol::socket socket2(my_io_context);
local::connect_pair(socket1, socket2);
可以通过将接受器绑定到端点来创建 UNIX 域套接字服务器,这与 TCP 服务器的方式非常相似:
::unlink("/tmp/foobar"); // Remove previous binding.
local::stream_protocol::endpoint ep("/tmp/foobar");
local::stream_protocol::acceptor acceptor(my_io_context, ep);
local::stream_protocol::socket socket(my_io_context);
acceptor.accept(socket);
连接此服务器的客户端代码如下:
local::stream_protocol::endpoint ep("/tmp/foobar");
local::stream_protocol::socket socket(my_io_context);
socket.connect(ep);
Asio 不直接支持跨 UNIX 域套接字传输文件描述符或凭据,但可以通过使用 native_handle()
成员函数访问套接字的底层描述符来实现。
注意:如果目标操作系统支持,UNIX 域套接字仅在编译时可用。 程序可以测试宏 BOOST_ASIO_HAS_LOCAL_SOCKETS
以确定它们是否受支持。
面向流的文件描述符
Asio 包括能在 POSIX 文件描述符(例如管道、标准输入和输出以及各种设备)上执行同步和异步读写操作的类。
这些类还为常规文件提供有限的支持。此支持假定操作系统提供的底层读写操作永远不会因 EAGAIN 或 EWOULDBLOCK 而失败。 (这个假设通常适用于缓冲文件 I/O。)文件描述符上的同步和异步读写操作将成功,但 I/O 将始终立即执行。不支持等待操作和涉及boost::asio::null_buffers
的操作。
例如,要对标准输入和输出执行读写操作,可以创建以下对象:
posix::stream_descriptor in(my_io_context, ::dup(STDIN_FILENO));
posix::stream_descriptor out(my_io_context, ::dup(STDOUT_FILENO));
然后将它们用作同步或异步读写流。 这意味着对象可以与任何 read()、async_read()、write()、async_write()、read_until()
或 async_read_until()
自由函数一起使用。
注意:如果目标操作系统支持,POSIX 流描述符仅在编译时可用。 程序可以测试宏 BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
以确定它们是否受支持。
Fork
Asio 支持使用 fork()
系统调用的程序。 如果程序在适当的时间调用 io_context.notify_fork()
,Asio 将重新创建任何内部文件描述符(例如用于唤醒reactor的“自管道技巧”描述符)。 通知通常执行如下:
io_context_.notify_fork(boost::asio::io_context::fork_prepare);
if (fork() == 0)
{
//子进程
io_context_.notify_fork(boost::asio::io_context::fork_child);
...
}
else
{
//父进程
io_context_.notify_fork(boost::asio::io_context::fork_parent);
...
}
用户定义的服务也可以通过覆盖 io_context::service::notify_fork()
虚函数感知 fork。
请注意,任何可通过 Asio 的公共 API 访问的文件描述符(例如,basic_socket<>、posix::stream_descriptor
等底层的描述符)在 fork 期间不会更改。 根据需要管理这些是程序的责任。