简体   繁体   English

从同一套接字发送和接收数据的简单 UDP 示例

[英]Simple UDP example to send and receive data from same socket

For some reason I am having a hard time sending and receiving data from the same socket.出于某种原因,我很难从同一个套接字发送和接收数据。 Anyways here is my client code:无论如何,这是我的客户端代码:

var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); // endpoint where server is listening (testing localy)
client.Connect(ep); 

// send data
client.Send(new byte[] { 1, 2, 3, 4, 5 }, 5);

// then receive data
var receivedData = client.Receive(ref ep);  // Exception: An existing connection was forcibly closed by the remote host

Basically I want to create a protocol where I send a udp packet and then I expect a response.基本上我想创建一个协议,在那里我发送一个 udp 数据包,然后我期待一个响应。 Just like the HTTP protocol for every request there is a response.就像 HTTP 协议对于每个请求都有一个响应。 This code works if the server is on a different computer.如果服务器位于不同的计算机上,则此代码有效。 There might be the case where the server and client are on the same computer though.可能存在服务器和客户端在同一台计算机上的情况。

Here is the server:这是服务器:

UdpClient udpServer = new UdpClient(UDP_LISTEN_PORT);

while (true)
{
    var groupEP = new IPEndPoint(IPAddress.Any, 11000); // listen on any port
    var data = udpServer.Receive(ref groupEP);
    udpServer.Send(new byte[] { 1 }, 1); // if data is received reply letting the client know that we got his data          
}

Edit编辑

the reason why I cannot use tcp is because sometimes the client is behind a NAT (router) and it is simpler to do UDP hole punching than TCP.我不能使用 tcp 的原因是有时客户端位于 NAT(路由器)后面,并且进行 UDP 打孔比 TCP 更简单。


Solution:解决方法:

thanks to markmnl answer here is my code:感谢 markmnl 回答这里是我的代码:

Server:服务器:

UdpClient udpServer = new UdpClient(11000);

while (true)
{
    var remoteEP = new IPEndPoint(IPAddress.Any, 11000); 
    var data = udpServer.Receive(ref remoteEP); // listen on port 11000
    Console.Write("receive data from " + remoteEP.ToString());
    udpServer.Send(new byte[] { 1 }, 1, remoteEP); // reply back
}

Client code:客户端代码:

var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); // endpoint where server is listening
client.Connect(ep);

// send data
client.Send(new byte[] { 1, 2, 3, 4, 5 }, 5);

// then receive data
var receivedData = client.Receive(ref ep);

Console.Write("receive data from " + ep.ToString());

Console.Read();

(I presume you are aware that using UDP(User Datagram Protocol) does not guarantee delivery, checks for duplicates and congestion control and will just answer your question). (我假设您知道使用 UDP(用户数据报协议)并不能保证交付、检查重复项和拥塞控制,并且只会回答您的问题)。

In your server this line:在您的服务器中,这一行:

var data = udpServer.Receive(ref groupEP);

re-assigns groupEP from what you had to a the address you receive something on.groupEP从您拥有的地址重新分配到您收到的地址。

This line:这一行:

udpServer.Send(new byte[] { 1 }, 1); 

Will not work since you have not specified who to send the data to.将不起作用,因为您尚未指定将数据发送给谁。 (It works on your client because you called connect which means send will always be sent to the end point you connected to, of course we don't want that on the server as we could have many clients). (它适用于您的客户端,因为您调用了 connect 这意味着 send 将始终发送到您连接的端点,当然我们不希望在服务器上这样做,因为我们可能有很多客户端)。 I would:我会:

UdpClient udpServer = new UdpClient(UDP_LISTEN_PORT);

while (true)
{
    var remoteEP = new IPEndPoint(IPAddress.Any, 11000);
    var data = udpServer.Receive(ref remoteEP);
    udpServer.Send(new byte[] { 1 }, 1, remoteEP); // if data is received reply letting the client know that we got his data          
}

Also if you have server and client on the same machine you should have them on different ports.此外,如果您在同一台机器上有服务器和客户端,您应该将它们放在不同的端口上。

I'll try to keep this short, I've done this a few months ago for a game I was trying to build, it does a UDP "Client-Server" connection that acts like TCP, you can send (message) (message + object) using this.我会尽量保持简短,几个月前我已经为我试图构建的游戏完成了这个,它执行了一个像 TCP 一样的 UDP“客户端-服务器”连接,你可以发送(消息)(消息+ 对象)使用这个。 I've done some testing with it and it works just fine, feel free to modify it if needed.我已经用它做了一些测试,它工作得很好,如果需要,请随时修改它。

here is my soln to define the remote and local port and then write out to a file the received data, put this all in a class of your choice with the correct imports这是我定义远程和本地端口的解决方案,然后将接收到的数据写入文件,将所有这些都放入您选择的具有正确导入的类中

    static UdpClient sendClient = new UdpClient();
    static int localPort = 49999;
    static int remotePort = 49000;
    static IPEndPoint localEP = new IPEndPoint(IPAddress.Any, localPort);
    static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), remotePort);
    static string logPath = System.AppDomain.CurrentDomain.BaseDirectory + "/recvd.txt";
    static System.IO.StreamWriter fw = new System.IO.StreamWriter(logPath, true);


    private static void initStuff()
    {
      
        fw.AutoFlush = true;
        sendClient.ExclusiveAddressUse = false;
        sendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        sendClient.Client.Bind(localEP);
        sendClient.BeginReceive(DataReceived, sendClient);
    }

    private static void DataReceived(IAsyncResult ar)
    {
        UdpClient c = (UdpClient)ar.AsyncState;
        IPEndPoint receivedIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
        Byte[] receivedBytes = c.EndReceive(ar, ref receivedIpEndPoint);
        fw.WriteLine(DateTime.Now.ToString("HH:mm:ss.ff tt") +  " (" + receivedBytes.Length + " bytes)");

        c.BeginReceive(DataReceived, ar.AsyncState);
    }


    static void Main(string[] args)
    {
        initStuff();
        byte[] emptyByte = {};
        sendClient.Send(emptyByte, emptyByte.Length, remoteEP);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM