【问题标题】:Sending UDP Broadcast for populating USR-TCP232 LAN Modules information发送 UDP 广播以填充 USR-TCP232 LAN 模块信息
【发布时间】:2017-02-01 00:41:01
【问题描述】:

我正在将 USR-TCP232 LAN 模块用于嵌入式项目。 我有一个工具可以查询制造商制造的那些模块,效果很好。 但是,我希望它在我的 C# 代码中。所以,我决定自己做一个。我相信我已经很接近了,但我猜是一个小故障,这给我带来了困难,我需要有人来解释一下。

我可以发送一个 UDP 广播,我可以通过“WireShark”观察流量。 它与原始工具非常相似。但是,我无法在我的代码中接收到网络上设备发送的应答数据。

C# 中的控制台应用程序

using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;

namespace UDPer
{
    class Program
    {
        static void Main(string[] args)
        {
            UDPer udp = new UDPer();
            udp.Starter();

            ConsoleKeyInfo cki;
            do
            {
                if (Console.KeyAvailable)
                {
                    cki = Console.ReadKey(true);
                    switch (cki.KeyChar)
                    {
                        case 's':
                            udp.Send("0123456789012345678901234567890123456789");

                            break;
                        case 'x':
                            udp.Stop();
                            return;
                    }
                }
                Thread.Sleep(10);
            } while (true);
        }
    }

    class UDPer
    {
        private Socket udpSock;
        private byte[] buffer;
        public void Starter()
        {
            //Setup the socket and message buffer
            udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            udpSock.Bind(new IPEndPoint(IPAddress.Any, 0));
            udpSock.EnableBroadcast = true;
            buffer = new byte[1024];

             udpSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            //udpSock.ExclusiveAddressUse = false; // only if you want to send/receive on same machine.

             //The socket must not be bound or connected.
            //Start listening for a new message.
            EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
            udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
        }

        public void Stop()
        {
            try
            {
                udpSock.Close();
                Console.WriteLine("Stopped listening");
            }
            catch { /* don't care */ }

        }
        private void DoReceiveFrom(IAsyncResult iar)
        {
            try
            {
                //Get the received message.
                Socket recvSock = (Socket)iar.AsyncState;
                recvSock.EnableBroadcast = true;
                EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
                int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
                byte[] localMsg = new byte[msgLen];
                Array.Copy(buffer, localMsg, msgLen);

                //Start listening for a new message.
                EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
                udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);

                //Handle the received message
                Console.WriteLine("Recieved {0} bytes from {1}:{2}",
                                  msgLen,
                                  ((IPEndPoint)clientEP).Address,
                                  ((IPEndPoint)clientEP).Port);
                //Do other, more interesting, things with the received message.
                string message = Encoding.ASCII.GetString(localMsg);
                Console.WriteLine("Message: {0} ", message);
            }
            catch (ObjectDisposedException)
            {
                //expected termination exception on a closed socket.
            }
        }

        public void Send(string message)
        {
            UdpClient udp = new UdpClient(1500);
            var ipEndPoint = new IPEndPoint(IPAddress.Broadcast, 1500);
            byte[] data = Encoding.ASCII.GetBytes(message);
            udp.Send(data, data.Length, ipEndPoint);
            udp.Close();
        }
    }
}

Wireshark 捕获

请注意:此 Wireshark 捕获与原始工具完全相同。

一些定义:

我的 C# 应用程序所在的 PC:192.168.65.82

局域网模块IP地址:192.168.65.8

端口必须是 1500,这一切都可以。

发送有效载荷以查询 LAN 模块; “0123456789012345678901234567890123456789”

所以,我一一尝试了很多不同的选项,但到目前为止还没有。 我在这里想念什么?

【问题讨论】:

  • 您如何了解设备如何发送数据?此外,他们的工具会知道他们的工作,所以它可以工作。您应该检查他们的 API(如果有),以便与设备正常通信。
  • @Am_I_Helpful,不要与设备混淆。在走这条路之前,我已经研究了制造商的要求。只要我发送到端口 1500 并使用确切的有效负载,即使是其他一些第三方 UDP 广播工具也可以正常工作。所以,这应该是我在代码中的某个地方的错。

标签: c# sockets udp broadcast


【解决方案1】:

套接字总是有一个专用端口。传递带有端口号 0 的 IPEndPoint 并不意味着您接收到发送到任何端口的数据包。相反,您正在绑定到由底层服务提供商分配的端口。

udpSock.Bind(new IPEndPoint(IPAddress.Any, 0));

如果您不关心使用哪个本地端口,您可以使用 0 作为端口号创建一个 IPEndPoint。在这种情况下,服务提供商将分配一个介于 1024 和 5000 之间的可用端口号

https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.bind(v=vs.110).aspx

你需要使用

udpSock.Bind(new IPEndPoint(IPAddress.Any, 1500));

【讨论】:

  • 是的,我知道,你是对的。事实上,我避免了这种情况,因为我在同一个应用程序中使用了发件人。当我分配与发送方套接字相同的端口时,应用程序会抱怨这一点。因为,我们不能再次将现有端口用于其他任务。这种通信是无连接通信。所以,没有打开和关闭,至少我从中理解。所以,如果接收部分分配端口 1500,我不能将它用于我必须的发件人:(
  • 发送和接收需要使用相同的 UdpClient 对象或相同的 Socket 对象。
  • 是的,就是这样。这是唯一的方法,现在效果很好。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-26
  • 2019-06-17
  • 2012-06-05
  • 2015-03-14
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多