8

inetdsystemd类型的系统中,系统可以绑定套接字并使用已经存在的套接字启动应用程序,例如提供基于套接字的服务启动。我想在我的一个 Haskell 守护程序中利用此功能。

守护进程当前调用 , ,socket来创建一个我以后可以调用的对象。要将其更改为类型系统,我需要将标准输入用作 a ,但到目前为止我能找到的只是, 或- 两者都不是我需要的。bindSocketlistenSocketacceptinetdSocketstdin :: HandlefdToHandle :: CInt -> Handle

我似乎找不到任何类型的东西Handle -> Socket,也找不到任何类似的东西stdin :: Socket。我能找到的最接近的mkSocket是非常低级的,并且大多数其他语言(即Ruby)都提供了将文件描述符转换为套接字的调用,而无需指定各种其他参数。

4

2 回答 2

4

C 应用程序拥有sd-daemon.h自动处理套接字传递的奢侈。在 Haskell 中,这个文件必须手动模拟。

您可以使用stdInput来获取stdin文件描述符。handleToFd当然也可以使用该功能。由于您需要特定于 POSIX 的行为,因此您不能指望它在 Windows 上运行。

一旦你有了FD,你别无选择,只能使用该mkSocket功能。Haskell 无法猜测你想要什么样的套接字,所以你必须指定它。你很可能想要:

mkSocket fd AF_UNIX Stream defaultProtocol Listening

请记住,这不一定是systemd将文件描述符传递给您的应用程序的方式。您必须检查LISTEN_FDSLISTEN_PID环境变量以查看要使用的文件描述符以及您的工作是否甚至绑定套接字。代表默认套接字的默认文件描述符是 FD 3,而不是您假设的 FD 0。systemd如果服务文件需要它,也可能会为您提供多个套接字供您使用。

于 2012-07-19T11:15:32.210 回答
1

MkSocket 的主要技巧是知道你有正确的参数。sd-daemon.h 对此有所帮助。我从sd_is_fifo 上的systemd 手册页看到它使用 fstat 和 getsockname,sd_is_socket 的代码在 git here中。

您可以使用fstat包裹在unix 包中来帮助

getFdStatus :: Fd -> IO FileStatus

isSocket :: FileStatus -> Bool

Network 包(部分使用 Network.Socket.Internals)也使用 Cgetsockname函数(帮助withNewSockAddr程序为答案分配正确的缓冲区)。这需要猜测“家庭”,或者可能只是为答案分配一个大缓冲区(sockaddr_storage来自 RFC 2553)。Socket但是 Network 从数据中获取套接字文件描述符。您可以从网络中提取代码并重新实现 sd-daemons.h 所做的检查。

此外,getsockopt代码可能已包装在network-socket-options 包中。

但似乎没有人按照您需要的方式将其组合在一起。奇怪的。

于 2012-07-19T12:54:17.290 回答