C++ UDP如何在同一个端口上发送和接收?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1640660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to UDP send and receive on same port?
提问by cedgriss
I need to be able to send and receive UDP packets on the same port. I am able to listen, on say port 5000, but my send uses a random high port. The system I am working written in VB with does this and my need is to write a UDP responder for debugging various protocol issues.
我需要能够在同一端口上发送和接收 UDP 数据包。我可以在端口 5000 上收听,但我的发送使用随机高端口。我正在使用 VB 编写的系统执行此操作,我需要编写一个 UDP 响应程序来调试各种协议问题。
I am using the Open Source C++ Sockets Library from http://www.alhem.net(Anders Hedstrom) and have been able to use the UdpSocket::Bind() to receive incoming UDP packets using the virtual function UdpSocket::OnRawData(), but have been unable to cause the UdpSocket::Open() (calls connect) to make the UdpSocket::Send() use the port chosen in Bind() (it uses random high number port instead).
我正在使用来自http://www.alhem.net(Anders Hedstrom) 的开源 C++ 套接字库,并且已经能够使用 UdpSocket::Bind() 使用虚拟函数 UdpSocket::OnRawData() 接收传入的 UDP 数据包),但无法使 UdpSocket::Open()(调用连接)使 UdpSocket::Send() 使用在 Bind() 中选择的端口(它使用随机高数端口)。
Moving the Open() function doesn't help. I have posted a request on their forum - but believe from what I have read that it should be possible to do this, and I'm probably not understanding how to use UDP.
移动 Open() 函数无济于事。我已经在他们的论坛上发布了一个请求 - 但从我所读到的内容中相信应该可以做到这一点,而且我可能不了解如何使用 UDP。
Does anyone have any ideas on what I should try?
--thanks--
有没有人对我应该尝试什么有任何想法?
- 谢谢 -
回答by sbk
System consists of a number of nodes listening on same port (different ip addr's). System [A] sends datagram to System [B]. System [B] asynchronously responds and send datagram(s) back to [A] all using same port. Even if [B] identifies [A]'s port, [A] is not listening on that port
系统由多个节点组成,这些节点侦听同一端口(不同的 ip 地址)。系统 [A] 向系统 [B] 发送数据报。系统 [B] 异步响应并将数据报发送回 [A],全部使用相同的端口。即使 [B] 识别出 [A] 的端口,[A] 也不会侦听该端口
I'm not sure I understand the "all using the same port" phrase in that sentence. If A sends a datagram to B, B will know A's IP and port right away (a quick check of your library documentation reveals OnRawData has a struct sockaddr *sa
parameter, if you cast it to sockaddr_in*
you'll be able to extract the IP:port pair). You can use that IP:port to send datagrams to and A will receive them. A is not "listening" on that port in the sense that it haven't called listen() on the socket, but since A owns a socket that is bound to that port (whether explicitly by calling bind() or assigned random port by the OS) it will receive the data.
我不确定我是否理解那句话中的“所有使用相同的端口”短语。如果 A 向 B 发送数据报,B 将立即知道 A 的 IP 和端口(快速检查您的库文档会发现 OnRawData 有一个struct sockaddr *sa
参数,如果您将其强制转换为sockaddr_in*
您将能够提取 IP:port 对)。您可以使用该 IP:port 向 A 发送数据报,A 将接收它们。A 没有在该端口上“侦听”,因为它没有在套接字上调用 listen(),但是由于 A 拥有一个绑定到该端口的套接字(无论是显式调用 bind() 还是分配的随机端口)操作系统)它将接收数据。
Now if you want ALL your communication between nodes to go through your fixed port, you can do that. You just have to send all your datagrams through your "listening" socket. If every node "listens" on the same port, it means every node owns a socket that is bound to that port. If you want datagrams sent from A to B to appear coming from this fixed port you have to send them through that socket. I'm guessing that's why bind() doesn't work for your sending socket - A has a socket bound to port X, then you create another socket and try to bind it to the same port X, bind() fails since the port is already taken (and you don't check for errors :), and then the OS assigns random free port above 1024.
现在,如果您希望节点之间的所有通信都通过您的固定端口,您可以这样做。您只需要通过“侦听”套接字发送所有数据报。如果每个节点都在同一个端口上“侦听”,则意味着每个节点都拥有一个绑定到该端口的套接字。如果您希望从 A 发送到 B 的数据报显示为来自此固定端口,则必须通过该套接字发送它们。我猜这就是为什么 bind() 不适用于您的发送套接字 - A 有一个套接字绑定到端口 X,然后您创建另一个套接字并尝试将其绑定到同一个端口 X,bind() 失败,因为端口已经被占用(并且您不检查错误:),然后操作系统分配 1024 以上的随机空闲端口。
Note 1: I use "listening" in quotes everywhere, because the concept is not very clear in the context of UDP sockets. Once you have created socket and bound it to a port, either by calling bind() explicitly or by sending data and letting the OS bind it to a port, you can receive data from everywhere through it. No listen() or accept() calls needed.
注 1:我到处都在引号中使用“listening”,因为在 UDP 套接字的上下文中这个概念不是很清楚。创建套接字并将其绑定到端口后,通过显式调用 bind() 或发送数据并让操作系统将其绑定到端口,您就可以通过它从任何地方接收数据。不需要 listen() 或 accept() 调用。
Note 2: You say that UdpSocket::Open() calls connect(), but that doesn't make much sense - connect() does very little for UDP sockets - it merely establishes a default address so you can use send() instead of sendto() and not specify address on every send.
注意 2:你说 UdpSocket::Open() 调用了 connect(),但这没有多大意义——connect() 对 UDP 套接字几乎没有作用——它只是建立一个默认地址,所以你可以使用 send() 代替sendto() 而不是在每次发送时指定地址。
Hope that clears things up.
希望这能说明问题。
编辑以解决 OP 的评论:我从未使用过这个库,但根据他们的 UdpSocket documentationUdpSocket 文档中有 4 个 Bind() 方法的重载,并且每个重载都以某种方式接受端口。他们都不适合你?
回答by jldupont
A bidirectional communication link always involves two participants: a server-side and a client-side.
双向通信链路始终涉及两个参与者:服务器端和客户端。
The client expects to communicate to a server on a defined port: that's why on the server-side one must bind() to a socket.
客户端期望通过定义的端口与服务器通信:这就是为什么在服务器端必须将 bind() 绑定到套接字。
On the client-side, one must open a socket to the server: it doesn't really matter which socket is chosen (except for the need for it to be free).
在客户端,必须向服务器打开一个套接字:选择哪个套接字并不重要(除了需要它是免费的)。
In other words, don't try to specify a socket on the client-side: the network protocol stack will assign it to your client.
换句话说,不要尝试在客户端指定套接字:网络协议栈会将其分配给您的客户端。