使用C# sockets发现Lantronix XPort Pro和XPort

3
我正在尝试使用C#查找网络上的Lantronix XPort Pro设备。我使用在Lantronix开发者wiki上找到的一些Python代码作为示例http://wiki.lantronix.com/developer/Lantronix_Discovery_Protocol
我正在编写的应用程序是用C#编写的,我需要发现已安装Lantronix设备的单元。当我执行socket.RecieveFrom函数调用时,似乎它只是使应用程序停顿了。
你有什么想法我做错了什么?来自上面链接的python代码正确地检测到设备。我应该能够在C#中复制它。
非常感谢您的任何帮助。
   private void FindLantronixXPort()
    {
        // This is the socket code that will broadcast from 
        // the local machine looking for responces from Lantronix
        // XPort servers

        // Create the array for our message chars
        char[] chars = new char[4];

        // Build the actual message
        chars[0] = Convert.ToChar(0);
        chars[1] = Convert.ToChar(0);
        chars[2] = Convert.ToChar(0);
        chars[3] = Convert.ToChar(0xf6);

        // Convert the chars to a message string
        string msg = new string(chars);

        // Convert the setring to a byte array
        byte[] data = Encoding.UTF8.GetBytes(msg);

        // Get the local machines IP address
        string Local_IP = GetIPAddress();

        // Now create a broadcast UDP socket
        Socket XmtSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        XmtSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);

        IPEndPoint iep = new IPEndPoint(IPAddress.Parse(Local_IP), LantronixPort);

        // Broadcast the packet
        XmtSock.SendTo(data, 0, data.Length, SocketFlags.None, iep);

        XmtSock.Close();

        // Wait 500 mili seconds
        int milliseconds = 500;
        System.Threading.Thread.Sleep(milliseconds);

        Socket RcvSock = new Socket(AddressFamily.InterNetwork,
            SocketType.Dgram, ProtocolType.Udp);

        iep = new IPEndPoint(IPAddress.Any, LantronixPort);

        RcvSock.Bind(iep);

        EndPoint ep = (EndPoint)iep;

        Console.WriteLine("Ready to receive...");

        byte[] data1 = new byte[120];

        int recv = RcvSock.ReceiveFrom(data1, data1.Length, SocketFlags.None, ref ep);

        string stringData = Encoding.ASCII.GetString(data1, 0, recv);

        Console.WriteLine("received: {0}  from: {1}",
                              stringData, ep.ToString());

        RcvSock.Close();
    }

我查看了你的链接的源代码。代码似乎连接到:"http://wiki.lantronix.com"。那么为什么你在你的C#代码中要尝试连接到一个UDP端口呢? - jdweng
“wiki.lantronix.com”网站上有一些Python代码示例,我正在尝试将其实现在C#中。但是我无法连接到该网站。该代码获取我的本地机器的IP地址,并使用它发送发现命令以查找Lantronix设备。我包含了Lantronix链接,以防有人想查看我所使用的Python代码示例。 - WJD
请查看以下帖子,可能会有所帮助:https://social.msdn.microsoft.com/Forums/en-US/4185e8f7-90dc-471e-a485-03567c64c816/how-to-capture-dhcpv6-ipv6-packets-in-c?forum=ncl - jdweng
2个回答

1
Lantronix的维基似乎暂时无法访问,所以我现在无法查看。不过,从你的代码来看,似乎你需要广播一个UDP消息,等待一段时间,然后检查是否有任何回应。
但是,看起来你正在创建一个全新的用于接收响应的套接字,但是只有在半秒钟后才这样做。很可能任何要响应的X-port在那之前就已经完成了(网络很快,X-port并不太慢等)。因此,我认为响应会命中您的操作系统网络堆栈,该堆栈会说“我不知道那应该去哪里”,仅在半秒钟后您才创建了适合接收操作系统网络堆栈已经丢弃为未知垃圾的响应的套接字。
所以,我建议您稍微调整一下。在传输广播消息之前设置接收套接字、绑定和端点,以便准备好等待响应。看看这是否有所帮助。

我也是这么想的。在发送UDP广播之前,接收套接字最好是打开并监听状态。我还建议研究异步方法。微软有一个很好的套接字示例,虽然他们使用BeginAccept而不是BeginReceiveFrom(=异步ReceiveFrom)。https://learn.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example - NoMad
Lantronix的维基已经恢复了http://wiki.lantronix.com/developer/Lantronix_Discovery_Protocol。这个Python代码做到了我想要的。我需要获取响应广播的XPort设备的IP地址。有没有办法在C#中实现这一点?我只需要检查返回数据包中的一个字节。如果正确,我需要确定响应设备的IP地址。这就是示例Python代码所做的。 - WJD
好的,我已经使用这段代码成功地从XPort设备中获取到了正确的响应。我转而使用异步调用。现在我需要获取响应设备的IP地址。在C#中有没有办法做到这一点?如果需要,我可以发布我的最新代码。 - WJD
@WJD,我不是第一手了解,但也许这看起来很有前途:https://dev59.com/p1fUa4cB1Zd3GeqPERTW - bazza
感谢大家的建议。我已经通过异步UDP套接字找到了XPort设备。我使用了 ((IPEndPoint)epServer1).Address.ToString() 来确定每个响应单元的IP地址。 - WJD

1
@WJD,你准备字节数组的代码没有创建XPort期望的内容。这就是为什么它没有回复并在RecieveFrom()上挂起的原因。 我按照你提供的Python示例链接创建了C#版本。
class Program
{
    static void Main(string[] args)
    {
        Socket socket;
        int GroupPort = 30718;
        try
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
            var localEP = new IPEndPoint(IPAddress.Parse("10.0.2.14"), GroupPort);    // <-- your local IP address

            socket.Bind(localEP);
            socket.ReceiveTimeout = 200;
        }
        catch (TimeoutException e)
        {
            Console.WriteLine("Failed to create socket. " + e.Message);
            return;
        }


        var remoteEP = new IPEndPoint(IPAddress.Broadcast, GroupPort);
        try
        {
            byte[] messageBytes;
            messageBytes = new byte[0];
            messageBytes = AddByteToArray(messageBytes, 0xf6);
            messageBytes = AddByteToArray(messageBytes, 0);
            messageBytes = AddByteToArray(messageBytes, 0);
            messageBytes = AddByteToArray(messageBytes, 0);

            socket.SendTo(messageBytes, remoteEP);
        }
        catch (Exception e)
        {
            Console.WriteLine("Failed to send message. " + e.Message);
            return;
        }


        var recvEp = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
        while (true)
        {
            try
            {
                var recvBytes = new byte[1024];
                var receivedCount = socket.ReceiveFrom(recvBytes, ref recvEp);
                var receivedArray = recvBytes.Take(receivedCount).ToArray();
                var receivedArrayAsHexString = string.Join("", receivedArray.Select(c => String.Format("{0:X2}", Convert.ToInt32(c))));
                string returnData = Encoding.ASCII.GetString(receivedArray);
                Console.WriteLine($"Broadcast Respond from client {recvEp.ToString()} returned: {receivedArrayAsHexString}");
            }
            catch (Exception e)
            {
                socket.Close();
                break;
            }
        }
        Console.ReadLine();
    }

    public static byte[] AddByteToArray(byte[] bArray, byte newByte)
    {
        byte[] newArray = new byte[bArray.Length + 1];
        bArray.CopyTo(newArray, 1);
        newArray[0] = newByte;
        return newArray;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接