我需要写一个TCP守护程序来响应我们的客户端软件,想知道有没有什么关于这方面的最佳实践。
我是否应该为每个新连接fork一个进程,还是像通常一样使用线程?
这取决于你的应用程序。线程和forking都可以是完全有效的方法,以及单线程事件驱动模型的第三种选择。如果你能更详细地解释一下你正在编写的内容,那么在给出建议时会更有帮助。
值得一提的是,以下是一些一般性的指导方针:
通常来说,forking将是最容易实现的,因为一旦你fork,你就可以基本上忽略所有其他连接;线程是因为需要额外的同步要求而更困难;事件循环由于需要将处理转换为状态机而更加困难;多个线程运行事件循环则是最困难的(由于结合了其他因素)。
inetd
或tcpserver
等非常简单地实现服务器:然后可以使用标准输入和标准输出与套接字进行通信,并且不必进行任何侦听套接字管理(侦听连接等)。当然,另一个选择是预先派生多个守护进程的副本,并使每个副本保持活动状态并继续响应请求。这完全取决于您的应用程序、预期负载和性能要求等因素。
最简单和最简单的方法是编写基于inetd的守护进程;您的软件可以忽略它正在通过TCP连接运行的事实,并通过stdin/stdout处理输入/输出。在绝大多数情况下,这种方式都很有效。
如果你不打算每秒处理大量的新连接,考虑从inetd运行。否则...
下载OpenSSH源代码。他们在特权分离方面做得非常好,它是可移植的,并且已经接受了比其他任何东西都更多的安全审查。
根据您的需求进行调整,您可能可以扔掉大部分内容。当然要遵守许可协议。使用良好的SCC跟随未来的补丁。
在没有充分证据表明这是一个真正的问题之前,不要担心fork进程与线程的性能差异。Apache使用简单的每个客户端模型运行最繁忙的站点多年。
如果你真的雄心勃勃,你可以使用某种非阻塞异步IO模型。我喜欢Boost.Asio,但我很重视C++。
确保您的代码正确处理信号。HUP重新加载配置。TERM优雅地关闭。
不要尝试编写自己的日志文件。仅使用syslog,或者只写入可以重定向到syslog的stderr。在所有记录略有不同的自制服务器上设置logrotate真的很麻烦。