UDP服务器,如何才能使每个线程收到正确的客户端数据包而不是其他?

时间:2014-10-15 16:50:56

标签: c linux sockets udp

好吧,我必须在Linux上用C做一个udp服务器。

这是我的问题,例如: 我有每个线程将管理客户端。但是recvfrom会接受来自任何来源的数据包,那么,每个线程如何才能接收到正确的客户端数据包呢?

我希望我能很好地解释我的问题。

谢谢!

(我的意思是我的服务器将为每个想要服务的客户端创建一个新线程。所以使用TCP我可以使用accept为每个线程 - 客户端连接设置一个“专用”套接字,但是使用UDP我可以'做同样的事。)

4 个答案:

答案 0 :(得分:3)

您不能同时从同一个套接字读取多个线程。

你应该做的是:

  1. 有一个专用线程接收所有入站数据包,查看源IP /端口,并根据需要将数据路由到适当的处理线程。

  2. 为每个处理线程提供自己的套接字bind()'到同一个本地IP /端口,connect()'编辑到它感兴趣的特定源IP /端口,然后每个线程可以独立调用recvfrom(),它只返回与线程期望的源匹配的数据包。

答案 1 :(得分:2)

UDP是基于消息的无连接协议。这里,在发送数据之前,客户端和服务器之间没有明确的连接/设置。它不会在客户端或服务器上维护任何通信状态。 UDP使用数据报套接字(SOCK_DGRAM)。这可确保以任何顺序发送或接收每个数据包,但保留消息边界。

TCP是基于流的面向连接的协议。这里,在交换数据之前,在客户端和服务器之间建立明确的逻辑连接。保持TCP状态以进行通信。 TCP使用流套接字(SOCK_STREAM)。这提供了面向连接的顺序数据流,其中包含用于创建/释放连接和检测错误的机制。

在TCP和UDP的标头中,仅存在端口号。 IP标头负责为路由添加必要的目标IP地址。但是,源IP地址应从源主机获得。

在TCP服务器和UDP服务器中,一旦使用特定套接字类型创建套接字,就会使用绑定系统调用将其绑定到端口。这样做是为了使客户端可以寻址到服务器的这个端口。 TCP客户端或UDP客户端中不需要绑定过程,因为它与客户端通信的任何端口无关。到目前为止,TCP服务器和UDP服务器都是一样的。

对于TCP服务器,将调用listen系统调用以侦听特定套接字上的连接。 listen表示可以排队的连接数限制,以及服务器进程已准备好接受套接字上的任何新传入连接。 服务器调用accept系统调用,这是一个等待传入连接的阻塞调用。 一旦新连接到来,就会创建一个新的套接字描述符,并在服务器和客户端之间建立连接。但是,作为服务器,它必须继续监听新连接。 这是多处理开始进入画面的地方。由于任何客户端都可以通过使用连接系统调用来触发连接,因此我们需要为新连接进行接受调用(阻塞调用)。此外,为了并行处理这些新连接,一种选择是分叉并创建子进程,当父进程在接受调用上等待新连接时,该进程将负责进一步处理新连接。这是在服务器中识别和处理/处理各个客户端连接的方式。简单来说,在并发服务器架构中,服务器上随时会有一个侦听套接字和多个连接套接字端点。

注意:来自客户端的连接系统调用会从客户端触发TCP SYN以启动3路握手过程。此时,客户端套接字状态为SYN_SENT,一旦SYN到达服务器,服务器套接字状态为SYN_RCVD。然后,服务器以SYN_ACK响应客户端,客户端将使用ACK响应,这将建立客户端和服务器之间的连接。

在UDP服务器的情况下,不需要这个初始连接建立,因为它是使用数据报套接字(SOCK_DGRAM)的基于消息的无连接协议。因此,UDP客户端将不需要用于连接建立的连接调用,这样就不需要在UDP服务器中监听和接受呼叫。因此,UDP客户端服务器体系结构应该是一种迭代体系结构,其中每个客户端请求/响应将被顺序处理,因为迭代服务器体系结构适用于消耗较少处理时间的UDP(轻量级)等服务。另请注意,由于处理所消耗的时间较少,因此迭代服务器的状态会更少。

在需要多个线程监听同一个套接字的情况下,你也可以选择基于select或epoll系统调用的软件架构,其中每个线程都在等待select select,但在这种情况下,它可能不是很好救命。可以满足您的要求的替代设计可以是用于接收,解析和分析的单独线程的组合。将指向多个处理线程的dispatch。

答案 2 :(得分:1)

这就是为什么你有一个端口号。

如果您的服务器正在侦听端口8080,则不允许其他进程将套接字绑定到该端口。

所有想要连接到此服务器的客户端都需要将其数据发送到服务器IP上的端口8080.

答案 3 :(得分:1)

UDP数据报有一个源IP和端口 - 你知道它来自哪里,所以你可以适当地路由它。

您可能需要一个专用线程发送到端口,维护状态,然后匹配请求的回复,以便可以发信号通知原始线程它自己的回复是可用的。这可以通过在请求结构中提供rx线程在匹配的答复到达时发出信号来进行回调来完成。回调可以发出始发线程正在等待的同步对象的信号。