Multithreading UDP和套接字对客户端的响应

Multithreading UDP和套接字对客户端的响应,multithreading,sockets,networking,udp,Multithreading,Sockets,Networking,Udp,我启动并运行了UDP通信。 在一个简单的分条版本中,客户机基本上是这样做的:是的,代码中有大量的ifs和错误检查;否,如果没有大量的定义,它将无法正常工作。但我在这里更多的是感性的,而不是实际的代码 sock = socket(AF_INET, SOCK_DGRAM, 0); server_length = sizeof(struct sockaddr_in); sendto(sock, "Hi", 3, 0, (struct sockaddr *)&myaddr, server_len

我启动并运行了UDP通信。 在一个简单的分条版本中,客户机基本上是这样做的:是的,代码中有大量的ifs和错误检查;否,如果没有大量的定义,它将无法正常工作。但我在这里更多的是感性的,而不是实际的代码

sock = socket(AF_INET, SOCK_DGRAM, 0);
server_length = sizeof(struct sockaddr_in);
sendto(sock, "Hi", 3, 0, (struct sockaddr *)&myaddr, server_length);
numRes = recvfrom(sock, (char *)buff, (int)sizeof(buff), 0, (struct sockaddr *)&myaddr, &server_length);
服务器基本上是一样的:

sock=socket(AF_INET, SOCK_DGRAM, 0);
bind(sock,(struct sockaddr *)&server,length);
resBytes=recvfrom(sock,buff,(int)sizeof(buff),0,(struct sockaddr *)&from, &fromlen);
sendto(sock, "Test",5, 0, (struct sockaddr *)&from, fromlen);
这很有效。两端接收另一端发送的数据

这是我的问题:服务器应该同时处理大量请求。我为这些消息建立了一个队列,以便另一个线程可以处理它们,然后在另一个线程中将它们发送回客户机。当我这样做的时候,我为发送创建了一个新的套接字,使用了与消息后面相同的from地址,但是客户端从未收到它

对UDP消息的应答必须使用相同的套接字进行理解是否正确

如果我使用同一个套接字发送和接收消息,如果我有三个客户端发送消息,那么在处理完这些消息后,我将以随机顺序回答它们。这样行吗

我可以在客户端上创建一个服务器,但我猜任何NAT都会很快扼杀这个想法

我试图尝试的或多或少是这样的:

sock=socket(AF_INET, SOCK_DGRAM, 0);
sock2=socket(AF_INET, SOCK_DGRAM, 0);

bind(sock,(struct sockaddr *)&server,length);
resBytes=recvfrom(sock,buff,(int)sizeof(buff),0,(struct sockaddr *)&from, &fromlen);

sendto(sock2, "Test",5, 0, (struct sockaddr *)&from, fromlen);
如果这类代码可以工作,我将返回调试,但现在看来情况并非如此

编辑:
有人添加了多线程作为标记。忘了多线程的事情吧,更重要的是解释为什么我不能及时响应相同的请求。如果需要的话,我可以在一个线程中进行所有通信。很抱歉,如果这让人感到困惑,但我这里的主要问题是:我可以在另一个socket上发送响应,而不在客户机上定义服务器。b如果没有,它将如何处理同一个套接字上的随机应答顺序,即客户端A发送、客户端b发送、应答客户端b,然后应答客户端A

只要套接字未连接,单个UDP套接字就可以从多个源接收数据并向多个对等方发送数据。这意味着,如果显式或隐式绑定套接字,然后使用sendto和recvfrom或recv,则可以使用同一套接字从多个对等方发送和接收数据。但是,如果首先连接套接字,则只能从绑定到连接的ip:端口的套接字接收数据,即通常是接收数据的同一套接字

为了测试这一点,您可以使用一个简单的Python服务器,它与C的工作原理相同。该服务器创建两个套接字:sock1和sock2。它将在sock1上接收消息,然后使用未接收原始消息的sock2和接收原始消息的sock1发回消息:

from socket import *

sock1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
sock2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)

sock1.bind(('127.0.0.1',9999))
data,addr = sock1.recvfrom(1024)
print("got '{}' from {}".format(data,addr))

sock2.sendto(b"send from sock2", addr)
sock1.sendto(b"send from sock1", addr)
作为对等方,我们有一个客户端,该客户端根据配置使用连接的套接字,即connect+send或未连接的套接字,即no connect and sendto:

如果在connected socket connected=True的情况下运行客户机,您将看到它将只从sock1返回消息,因为sock1显式绑定到客户机连接的ip:端口,而sock2隐式绑定到其他地址:

got 'send from sock1' from ('127.0.0.1', 9999)
如果客户端使用的是未连接的socket connected=False,则它将接收来自sock1和sock2的消息:


套接字不能由多个线程共享。但由于UDP是一种无连接协议,您可以使用不同的套接字来接收和发送。@user0042:套接字不能由多个线程共享。当然可以。这只是访问如何同步的问题。@alk好吧,同步有点违背了使用单独线程的目的,不是吗?好吧,忽略线程问题。如果需要,我可以将发送者和接收者放在同一个循环中。这里的主要问题是:能否在另一只袜子上发送响应。b如果我以随机顺序回复几个请求呢?非常感谢。这是回答我的问题。据我所知,我没有连接从两个插座发回的一个。那么我的代码一定有问题。@AslakBerby:如果您有一个设备在客户端和服务器之间进行NAT,那么它通常会创建一个由ip、连接两侧的端口组成的状态,并且只允许来自服务器的符合此状态的包通过。在此特定示例中:从sock1发送的数据包将通过NAT设备,而从sock2发送的数据包将被丢弃,因为没有匹配状态。这同样适用于有状态防火墙,即使它们不进行NAT。我开始意识到这一点。由于现在大多数家庭与互联网之间都有某种NAT,我必须保证它能与NAT一起工作,然后再使用连接版本。我将所有UDP代码移到同一个类中,并且只使用一个套接字。我只需要做一些测试,看看我可以连接多个客户端。
got 'send from sock1' from ('127.0.0.1', 9999)
got 'send from sock2' from ('127.0.0.1', 44596)
got 'send from sock1' from ('127.0.0.1', 9999)