我必须使用 UDP 套接字编写一个程序,但我无法理解在我遇到的情况下应该做什么。
我有一个服务器和一个客户端。服务器在 INADDR_ANY 套接字上接收数据报,对于出现的每个唯一客户端,它将向 sendto() 发送大量信息。每个客户端还定期向服务器发送数据。
对于每个联系监听套接字的客户端,我们将其称为 0,我为其创建一个单独的套接字,这样我就可以向其发送数据而不会阻塞套接字 0。我想要做的是将与特定客户端的所有通信移至新的套接字插座。我可以这样做吗?目标是使通信更轻松、高效并避免堵塞任何套接字。
所以我未能找到答案的问题是:
我知道 TCP 会更好,但我必须使用 UDP。我该怎么做?处理此类情况是否有公认的“标准”?
评论:我有一种感觉,我误解了 UDP 套接字,但与 TCP 相比,关于它的教程确实很少。
我想做的是将与特定客户的所有通信转移到 新的套接字。我可以这样做吗?
您可以创建一个新的 UDP 套接字,将其绑定()到另一个端口,然后指示客户端开始将流量发送到新套接字的端口而不是通常的端口;但请注意,这样做并没有真正获得任何优势。
如果不是,所有客户端写入套接字 0 时不会阻塞它吗? 不会经常进行recvfrom吗?
是的,但通常的解决方案是足够频繁地调用 recvfrom() 以跟上传入流量的流量,和/或增加其 SO_RECVBUF 缓冲区大小以使其传入数据缓冲区足够大,以至于不太可能成为满的。 确保recvfrom() 被足够频繁地调用的一种方法是创建一个单独的线程,该线程除了在循环中调用recvfrom() 之外不执行任何操作,然后将数据移交给另一个线程以进行更密集的处理。如果可能的话,以更高的优先级运行此网络线程,以确保它不会被其他线程占用 CPU。
如果可以在单独的客户端上接收来自特定客户端的数据 套接字,该数据会同时到达套接字 0 和特定套接字吗?
如果你有两个线程都在同一个套接字上调用recvfrom(),那么任何给定的传入UDP数据包都将被传递到一个线程或另一个线程,并且不可能预测哪个线程将接收哪个数据包——它只是抽签的运气取决于特定线程调用 recvfrom() 时套接字传入缓冲区中的下一个数据包是什么。一般来说,不推荐使用多个线程访问单个套接字的设计。
我知道 TCP 会更好,但我必须使用 UDP。如何 我应该这样做吗?是否有处理此类问题的公认“标准” 情况?
我不知道什么是“标准”,但我通常有一个专用的 I/O 线程,它除了从 UDP 套接字读取(如果需要,还可以写入)什么也不做。它将 UDP 套接字设置为非阻塞模式,然后循环 select() 到 recvfrom() 任何传入的 UDP 数据包,并将传入数据包的数据及其源地址/端口信息附加(以线程安全的方式)到供其他(时间不太敏感)线程取出并稍后处理的 FIFO 队列。这样,即使一个数据包(或系列或数据包)需要相对较长的时间来处理,结果也不会是数据包被丢弃(尽管随着 FIFO 变大,它可能会暂时增加 RAM 使用量)
@ Jeremy Friesner:你写道:“……即使如此,我的直觉是,两个套接字中的哪一个接收到任何特定的数据包将是不确定的/不可预测的——并且如果你的 connect() 套接字接收到了其他人的数据包,那么这将是不确定的/不可预测的。数据包,我怀疑数据包会被丢弃/过滤”。 正是这一点,我在 Linux 和 lwIP 中进行了调查,结果是:后来创建的套接字(具有较高的 fd 编号)是接收套接字,而另一个则不接收。
我也面临着类似的问题。