[英]How can I inherrit a socket in a child process on Windows using Boost.Asio and Boost.Procees?
我正在編寫一個多進程套接字服務器,在 Linux 上它工作得很好,但在 Windows 上它只是崩潰而沒有任何錯誤。 我相信這是因為它實際上並沒有正確繼承套接字文件描述符。
下面是我的代碼的精簡版本,它只打印子進程中的所有文件描述符。 在我的 windows VM 上,它會打印一個 FD 列表,但它從父進程傳遞的 FD 不在列表中,它高於列出的任何一個。
我找到了有關如何繼承套接字的 windows 文檔: https://docs.microsoft.com/en-us/windows/win32/sysinfo/handle-inheritance
我還發現 Boost.Process 具有此屬性,這表明默認情況下處理程序是繼承的: https://www.boost.org/doc/libs/1_78_0/doc/html/boost/process/limit_handles.html
但目前尚不清楚為什么我的套接字沒有被繼承,以及如何處理它。
#include <stdio.h>
#include <string>
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <boost/process/handles.hpp>
using boost::this_process::native_handle_type;
using namespace boost::asio;
using ip::tcp;
int main(int argc, char const *argv[])
{
int port = 5923;
if (argc == 2 && strcmp(argv[1], "--help")==0) {
printf("%s [port]\n", argv[0]);
return 0;
} else if (argc == 3 && strcmp(argv[1], "--child")==0) {
printf("child process\n");
int fd = std::stoi(argv[2]);
auto hds = boost::this_process::get_handles();
for (auto h : hds) {
std::cout << h << std::endl;
}
printf("got FD %d\n", fd);
return 0;
} else if (argc == 2)
{
port = std::stoi(argv[1]);
}
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v6(), port));
while (1)
{
printf("waiting for clients\n");
tcp::socket peersocket(io_service);
acceptor.accept(peersocket);
auto endpoint = peersocket.remote_endpoint();
printf("Accepted new connection from a client %s:%d\n", endpoint.address(), endpoint.port());
std::string fd = std::to_string(peersocket.release());
std::cout << fd << std::endl;
boost::process::spawn(argv[0], "--child", fd);
}
return 0;
}
好的,我找到了答案,它實際上是超級簡單的 EOF
Jk,我將把解決方案留給未來的我或其他迷失的靈魂。
您必須編寫一個“擴展”以使 Windows 繼承句柄。 https://www.boost.org/doc/libs/1_78_0/doc/html/boost_process/extend.html
windows_executor的屬性在這里解釋: windows_executor
://www.boost.org/doc/libs/1_78_0/doc/html/boost/process/extend/windows_executor.html
所以我們需要做的就是注冊一個on_setup
擴展並將inherit_handles
設置為true。 像這樣的東西:
struct do_inherit : boost::process::extend::handler
{
template<typename Char, typename Sequence>
void on_setup(ex::windows_executor<Char, Sequence> & exec)
{
std::cout << "windows setup" << std::endl;
exec.inherit_handles = 1;
}
template<typename Sequence>
void on_setup(ex::posix_executor<Sequence> & exec)
{
std::cout << "unix setup" << std::endl;
}
};
有了這些現代技術,我們終於可以做inetd
幾十年前所做的事情,但現在有了更多的模板 generics 和 Windows。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.