C# 在同一台计算机上的两个程序之间发送和接收UDP数据包
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/687868/
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
Sending and receiving UDP packets between two programs on the same computer
提问by Cecil Has a Name
Is it possible to get two separate programs to communicate on the same computer (one-way only) over UDP through localhost/127... by sharing the same port #?
是否可以通过 localhost/127 通过 UDP 在同一台计算机上(仅单向)让两个单独的程序通过共享相同的端口号进行通信?
We're working on a student project in which we need to send UDP packets containing some telemetry between two computers. The program that generates these packets is proprietary, but I'm working on the receiver program myself with C# using System.Net.Sockets.UdpClientand System.Net.IPEndPoint.
我们正在开展一个学生项目,我们需要在两台计算机之间发送包含一些遥测数据的 UDP 数据包。生成这些数据包的程序是专有的,但我正在使用System.Net.Sockets.UdpClient和System.Net.IPEndPoint使用 C# 自己编写接收器程序。
This works fine during our group's meetings when we have multiple computers connected on which we can run the two programs separately. But it's not very useful when I'm home and trying to expand on the telemetry processing program as I only have one computer (I need a feed for testing the processing program). I can not install the program on any of the school's computers either.
当我们连接了多台计算机,我们可以分别运行这两个程序时,这在我们小组的会议期间工作得很好。但是当我在家并尝试扩展遥测处理程序时,它并不是很有用,因为我只有一台计算机(我需要一个用于测试处理程序的提要)。我也无法在学校的任何计算机上安装该程序。
When I try to run both programs on my computer at the same time (starting my program last) I get a SocketException saying that only a single use of each port is normallyallowed. Which leads me to believe there must be some way to share the port (although it makes sense that only a single program can use port on a computer at any one time, I have no trouble running multiple internet browsers at the same time (and I suppose they use port 80 for http)).
当我尝试在我的计算机上同时运行这两个程序(最后启动我的程序)时,我收到一个 SocketException,说每个端口通常只允许使用一次。这让我相信必须有某种方式来共享端口(尽管在任何时候只有一个程序可以使用计算机上的端口是有道理的,但我同时运行多个互联网浏览器没有问题(而且我假设他们将端口 80 用于 http))。
REEDIT of the EDIT:
编辑的重新编辑:
sipwiz was right, and thanks to Kalmi for the pointer to UdpClient.Client.Bind(). At the time, though, we are considering using another program that generates similar packets, and with which we are able to share port with on the same computer using my first (although naive) approach with the UDP client binding in the ctor. Sorry for having to unmark your answer, sysrqb.
sipwiz 是对的,感谢 Kalmi 提供指向 UdpClient.Client.Bind() 的指针。不过,当时我们正在考虑使用另一个程序来生成类似的数据包,并且我们可以使用我的第一个(虽然很幼稚)的方法与 ctor 中的 UDP 客户端绑定在同一台计算机上共享端口。很抱歉不得不取消标记您的答案,sysrqb。
采纳答案by Tarnay Kálmán
I did not expect this to be possible, but.. well.. sipwizwas right.
我没想到这是可能的,但是.. 好吧.. sipwiz是对的。
It can be done very easily. (Please vote sipwiz's answer up!)
它可以很容易地完成。(请投票支持 sipwiz 的回答!)
IPEndPoint localpt = new IPEndPoint(IPAddress.Any, 6000);
//Failed try
try
{
var u = new UdpClient(5000);
u.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpClient u2 = new UdpClient(5000);//KABOOM
u2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
catch (Exception)
{
Console.WriteLine("ERROR! You must call Bind only after setting SocketOptionName.ReuseAddress. \n And you must not pass any parameter to UdpClient's constructor or it will call Bind.");
}
//This is how you do it (kudos to sipwiz)
UdpClient udpServer = new UdpClient(localpt); //This is what the proprietary(see question) sender would do (nothing special)
//!!! The following 3 lines is what the poster needs...(and the definition of localpt (of course))
UdpClient udpServer2 = new UdpClient();
udpServer2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer2.Client.Bind(localpt);
回答by rmmh
Only one program can bindto a port at a time. Multiple programs can connectto one port on another system's, but the local port your different web browsers have bound themselves to is randomly assigned.
一次只能有一个程序绑定到一个端口。多个程序可以连接到另一个系统上的一个端口,但是您的不同 Web 浏览器绑定的本地端口是随机分配的。
Unless you want to do some ugly inter-process communication or packet sniffing, there's no way to have multiple programs bound to one port.
除非你想做一些丑陋的进程间通信或数据包嗅探,否则没有办法将多个程序绑定到一个端口。
回答by sipwiz
You can bind to a port multiple times using the ReuseAddress socket option.
您可以使用 ReuseAddress 套接字选项多次绑定到一个端口。
UdpClient udpClient = new UdpClient();
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
You'll need to set the same option on the UDP server socket as well.
您还需要在 UDP 服务器套接字上设置相同的选项。
回答by Douglas Leeder
You might be able to put multiple IP addresses on your network card, or loopback, and bind the server and client to different IP addresses?
您是否可以在网卡或环回上放置多个 IP 地址,并将服务器和客户端绑定到不同的 IP 地址?
Or else the Virtual machine approach will definitely work.
否则虚拟机方法肯定会奏效。
回答by mpontillo
My advice: don't pass the port number into the UdpClient constructor. From the documentation, (somewhat sparse, I know...) it looks like if you do, the UdpClient will try to bindto that port (which, as sysrqb mentioned, is not allowed). (If you don't, I believe the UdpClient will listen on a random port for any replies. You could also pick a port you know to be unused.)
我的建议:不要将端口号传递给 UdpClient 构造函数。从文档中,(有点稀疏,我知道......)看起来如果你这样做,UdpClient 将尝试绑定到该端口(正如 sysrqb 所提到的,这是不允许的)。(如果你不这样做,我相信 UdpClient 会在一个随机端口上监听任何回复。你也可以选择一个你知道未使用的端口。)
When you call Connect() you need to pass in the port number the server is listeningon.
当您调用 Connect() 时,您需要传入服务器正在侦听的端口号。
回答by Tarnay Kálmán
bind the two programs,ie, the sender and receiver to the same port on the localhost.dats the simple answer.
将两个程序(即发送方和接收方)绑定到 localhost.dats 上的相同端口,这是简单的答案。
回答by MethodMan
Even changing your code so that I can pass in an IP address I gets the same error message it appears that you can't bind to the same port and only one port can be used here is the sample code I used your example and Altered it to capture my ip from my local machine.. IPAddress ipAddress = Dns.Resolve(Dns.GetHostName()).AddressList[0]; IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 11000);
即使更改您的代码以便我可以传入 IP 地址,我也会收到相同的错误消息,似乎您无法绑定到同一端口,并且此处只能使用一个端口,这是我使用您的示例并对其进行了更改的示例代码从我的本地机器捕获我的 ip.. IPAddress ipAddress = Dns.Resolve(Dns.GetHostName()).AddressList[0]; IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 11000);
//IPEndPoint localpt = new IPEndPoint(ipLocalEndPoint);
UdpClient udpServer = new UdpClient(ipLocalEndPoint);
udpServer.Client.SetSocketOption(
SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Connect(ipLocalEndPoint);
UdpClient udpServer2 = new UdpClient();
udpServer2.Client.SetSocketOption(
SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer2.Client.Bind(ipLocalEndPoint); // <<---------- Exception here
this will produce the exception on the Bind () method.. sorry.
这将在 Bind () 方法上产生异常.. 抱歉。
回答by epotter
Here is the full code from the answers by Tarnay Kálmán and sipwiz:
以下是 Tarnay Kálmán 和 sipwiz 回答的完整代码:
The server code:
服务器代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace UdpBroadcastTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Sender");
// This constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient();
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Connect("localhost", 11000);
try
{
string message = String.Empty;
do
{
message = Console.ReadLine();
// Sends a message to the host to which you have connected.
Byte[] sendBytes = Encoding.ASCII.GetBytes(message);
udpClient.Send(sendBytes, sendBytes.Length);
} while (message != String.Empty);
udpClient.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("Press Any Key to Continue");
Console.ReadKey();
}
}
}
The client code:
客户端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace UdpReciever
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Receiver");
// This constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient();
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 11000));
try
{
//IPEndPoint object will allow us to read datagrams sent from any source.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
string message = String.Empty;
do
{
// Blocks until a message returns on this socket from a remote host.
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
message = Encoding.ASCII.GetString(receiveBytes);
// Uses the IPEndPoint object to determine which of these two hosts responded.
Console.WriteLine("This is the message you received: " +
message);
//Console.WriteLine("This message was sent from " +
// RemoteIpEndPoint.Address.ToString() +
// " on their port number " +
// RemoteIpEndPoint.Port.ToString());
}
while (message != "exit");
udpClient.Close();
//udpClientB.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("Press Any Key to Continue");
Console.ReadKey();
}
}
}