【发布时间】:2013-09-21 19:19:21
【问题描述】:
我正在做一些网络测试,我正在使用 2 个仅使用函数的小型 C 程序连接 linux 机器:
connect()
连接后进行一些小计算并将其记录到本地文件中,我指示其中一个程序关闭连接,然后在同一端口上运行 netcat 侦听器。然后第一个程序重试连接并连接到 netcat。
我想知道是否有人可以建议是否可以在释放端口的同时保持初始连接并将连接传递给该端口上的 netcat(这样初始连接就不会关闭)。
【问题讨论】:
我正在做一些网络测试,我正在使用 2 个仅使用函数的小型 C 程序连接 linux 机器:
connect()
连接后进行一些小计算并将其记录到本地文件中,我指示其中一个程序关闭连接,然后在同一端口上运行 netcat 侦听器。然后第一个程序重试连接并连接到 netcat。
我想知道是否有人可以建议是否可以在释放端口的同时保持初始连接并将连接传递给该端口上的 netcat(这样初始连接就不会关闭)。
【问题讨论】:
每个 TCP 连接由四元组(目标 IP 地址、目标端口、源 IP 地址、源端口)定义,因此无需“释放”任何一台机器上的端口。
服务器进程在accept()建立新连接后立即fork() 是很常见的。父进程关闭其连接描述符的副本(由accept() 返回),并等待新的连接。子进程关闭原始套接字描述符,并执行应处理实际连接的所需程序或脚本。在许多情况下,孩子将连接描述符移动到标准输入和标准输出(使用dup2()),因此执行的脚本或程序甚至不需要知道它已连接到远程客户端:它写入标准输出的所有内容都是发送到远程客户端,并且远程客户端发送的所有内容都可以从标准输入中读取。
如果存在应该处理连接的现有进程,并且两个进程之间存在 Unix 域套接字连接(流、数据报或 seqpacket 套接字;没有区别),则可以将连接描述符作为SCM_RIGHTS 辅助消息。有关详细信息,请参阅 man 2 sendmsg、man 2 recvmsg、man 3 cmsg 和 man 7 unix。这仅适用于 Unix 域套接字上的同一台机器,因为内核实际上将描述符从一个进程复制到另一个进程;确实,内核做了一些时髦的魔法来实现这一点。
如果您的服务器端逻辑类似于
那么我推荐使用pthreads。只需创建所需数量的线程,通过在侦听套接字上调用accept() 让所有线程等待传入连接,并让每个线程自己处理连接。您甚至可以将stdio.h I/O 用于文件I/O。对于更复杂的输出——每个块多个语句——你需要一个pthread_mutex_t 每个输出流,并记住在释放互斥体之前fflush() 它。我怀疑一个单一的多线程程序可以完成所有这些,并且如果被中断(SIGINT aka CTRL+C)会很好地退出,不应该超过三百行 C。
【讨论】:
如果只需要从流套接字输出数据,或者只需要向其写入输入,则可以将其视为文件句柄。
因此,在 Posix 程序中,您可以使用 dup2() 将套接字句柄复制为值 1,这是标准输出。然后关闭原始手柄。然后使用 exec() 用“cat”覆盖你的程序,这将写入标准输入的输出,也就是文件句柄 1,也就是你的套接字。
【讨论】: