簡體   English   中英

如何構造 UDP 數據包但不發送

[英]How to construct UDP packet but not send it

這是一個奇怪的要求。

我有一個字節數組,我需要使用 C# 通過串行端口將其發送到另一個設備。 但是我需要首先將字節數組包裝在 udp 數據包中,但同樣,它將通過串行端口發送,而不是通過 udp。 有沒有辦法將 udp 數據包構造為字節數組,然后通過串口發送?

我以前使用 udp 發送和接收消息,但從來沒有在構造 udp 數據包但未通過 udp 發送的位置發送和接收消息。

我將接受 Yochai 的回答,因為該鏈接(以及該站點內的其他頁面)提供了構建 udp 數據包和 ip Z099FB995346F31C749F6E40DB0F395EE3 的代碼。 對於其他試圖完成它的人,這里是代碼:

如何稱呼它:

var udpPacketBytes = UDPPacket.Construct(IPAddress.Parse("1.1.1.1"), 1000, IPAddress.Parse("2.2.2.2"), 6100, payloadBytes);

UDP包class:

public static class UDPPacket
    {
        public static byte[] Construct(IPAddress sourceAddress, ushort sourcePort, IPAddress destinationAddress, ushort destinationPort, byte[] payload)
        {
            var bindAddress = IPAddress.Any;

            // Make sure parameters are consistent
            //if ((sourceAddress.AddressFamily != destinationAddress.AddressFamily) || (sourceAddress.AddressFamily != bindAddress.AddressFamily))
            //{
            //    throw new Exception("Source and destination address families don't match!");
            //}

            // Start building the headers
            byte[] builtPacket;
            UdpHeader udpPacket = new UdpHeader();
            ArrayList headerList = new ArrayList();
            //Socket rawSocket = null;
            //SocketOptionLevel socketLevel = SocketOptionLevel.IP;

            // Fill out the UDP header first
            Console.WriteLine("Filling out the UDP header...");
            udpPacket.SourcePort = sourcePort;
            udpPacket.DestinationPort = destinationPort;
            udpPacket.Length = (ushort)(UdpHeader.UdpHeaderLength + payload.Length);
            udpPacket.Checksum = 0;

            if (sourceAddress.AddressFamily == AddressFamily.InterNetwork)
            {
                Ipv4Header ipv4Packet = new Ipv4Header();

                // Build the IPv4 header
                Console.WriteLine("Building the IPv4 header...");
                ipv4Packet.Version = 4;
                ipv4Packet.Protocol = (byte)ProtocolType.Udp;
                ipv4Packet.Ttl = 2;
                ipv4Packet.Offset = 0;
                ipv4Packet.Length = (byte)Ipv4Header.Ipv4HeaderLength;
                ipv4Packet.TotalLength = (ushort)System.Convert.ToUInt16(Ipv4Header.Ipv4HeaderLength + UdpHeader.UdpHeaderLength + payload.Length);
                ipv4Packet.SourceAddress = sourceAddress;
                ipv4Packet.DestinationAddress = destinationAddress;

                // Set the IPv4 header in the UDP header since it is required to calculate the
                //    pseudo header checksum
                Console.WriteLine("Setting the IPv4 header for pseudo header checksum...");
                udpPacket.ipv4PacketHeader = ipv4Packet;

                // Add IPv4 header to list of headers -- headers should be added in th order
                //    they appear in the packet (i.e. IP first then UDP)
                Console.WriteLine("Adding the IPv4 header to the list of header, encapsulating packet...");
                headerList.Add(ipv4Packet);
                //socketLevel = SocketOptionLevel.IP;
            }
            else if (sourceAddress.AddressFamily == AddressFamily.InterNetworkV6)
            {
                Ipv6Header ipv6Packet = new Ipv6Header();

                // Build the IPv6 header
                Console.WriteLine("Building the IPv6 header...");
                ipv6Packet.Version = 6;
                ipv6Packet.TrafficClass = 1;
                ipv6Packet.Flow = 2;
                ipv6Packet.HopLimit = 2;
                ipv6Packet.NextHeader = (byte)ProtocolType.Udp;
                ipv6Packet.PayloadLength = (ushort)(UdpHeader.UdpHeaderLength + payload.Length);
                ipv6Packet.SourceAddress = sourceAddress;
                ipv6Packet.DestinationAddress = destinationAddress;

                // Set the IPv6 header in the UDP header since it is required to calculate the
                //    pseudo header checksum
                Console.WriteLine("Setting the IPv6 header for pseudo header checksum...");
                udpPacket.ipv6PacketHeader = ipv6Packet;

                // Add the IPv6 header to the list of headers - headers should be added in the order
                //    they appear in the packet (i.e. IP first then UDP)
                Console.WriteLine("Adding the IPv6 header to the list of header, encapsulating packet...");
                headerList.Add(ipv6Packet);
                //socketLevel = SocketOptionLevel.IPv6;
            }

            // Add the UDP header to list of headers after the IP header has been added
            Console.WriteLine("Adding the UDP header to the list of header, after IP header...");
            headerList.Add(udpPacket);

            // Convert the header classes into the binary on-the-wire representation
            Console.WriteLine("Converting the header classes into the binary...");
            builtPacket = udpPacket.BuildPacket(headerList, payload);

            /*
            // Create the raw socket for this packet
            Console.WriteLine("Creating the raw socket using Socket()...");
            rawSocket = new Socket(sourceAddress.AddressFamily, SocketType.Raw, ProtocolType.Udp);

            // Bind the socket to the interface specified
            Console.WriteLine("Binding the socket to the specified interface using Bind()...");
            rawSocket.Bind(new IPEndPoint(bindAddress, 0));

            // Set the HeaderIncluded option since we include the IP header
            Console.WriteLine("Setting the HeaderIncluded option for IP header...");
            rawSocket.SetSocketOption(socketLevel, SocketOptionName.HeaderIncluded, 1);

            try
            {
                // Send the packet!
                Console.WriteLine("Sending the packet...");
                int rc = rawSocket.SendTo(builtPacket, new IPEndPoint(destinationAddress, destinationPort));
                Console.WriteLine("send {0} bytes to {1}", rc, destinationAddress.ToString());
            }
            catch (SocketException err)
            {
                Console.WriteLine("Socket error occurred: {0}", err.Message);
                // http://msdn.microsoft.com/en-us/library/ms740668.aspx
            }
            finally
            {
                // Close the socket
                Console.WriteLine("Closing the socket...");
                rawSocket.Close();
            }
            */

            return builtPacket;
        }
    }

協議類:(此處發布太長)

協議 Class 代碼

您應該通過創建一個包含標准 UDP class 的 UDP class 來構建您的 UDP 數據包,該數據包包含標准 ZF5EF036B4D8B69FFE234 數據包中包含的所有數據。

數據如下

源端口 [SP](16 位) :當嘗試連接或進行連接時,它指定本地機器等待偵聽來自目標機器的響應的端口。

目標端口 [DP](16 位) :當用戶希望連接到遠程機器上的服務時,應用層程序指定初始連接應使用的端口。 當不作為初始連接的一部分時,這指定了在將數據包發送到其目的地時遠程機器將使用哪個端口號。

長度 [Len](16 位) :這允許接收站知道有多少輸入位應該是有效數據包的一部分。 長度是計算有多少字節是 UDP 數據包的一部分,包括 header 中的字節。 由於 UDP 在 header 中始終有 4 個字段,每個字段有 16 位,並且數據/有效負載長度可變,我們知道長度將為 8 +(有效負載中的字節數)。

UDP Checksum [UDPCS] (16 bits) :This is a checksum that covers the header and data portion of a UDP packet to allow the receiving host to verify the integrity of an incoming UDP packet. UDP 數據包在校驗和字段中加載了預定義的數字,然后在計算校驗和時,將校驗和覆蓋先前的值。 當數據包到達目的地時,目標機器的操作系統會查看 4 header 字段(從第 16 位到第 31 位組成的字節)並將它們從數據包中取出,然后重新計算數據包上的校驗和,校驗和字段中沒有任何內容. 然后操作系統將計算的校驗和與數據包中傳輸的校驗和進行比較。 如果校驗和相同,則數據正常,允許通過,但如果有差異,則UDP數據包,數據被丟棄,接收機器不嘗試獲取新的復制,並且發送機器不會嘗試發送相同的數據包。 數據包永遠丟失。 UDP 不可靠。 有關可靠的傳輸層 TCP/IP 套件協議,請參閱 TCP 數據包。

數據(可變位) :如您所料,這是 UDP 數據包的有效負載或數據部分。 有效負載可以是任意數量的協議(通常是應用層)。一些最常用的 UDP 協議包括 NFS、DNS 以及多種音頻和視頻流協議。 如果 UDP 數據包中發生錯誤並且需要修復錯誤,則由應用層查找錯誤並請求其應用層“大塊”或“塊”數據。

制作一個 class 來保存所有這些數據並適當地填充它,重載ToString以允許您然后轉換為 Byte 數組。

希望這可以幫助。

我想我在 .NET 的UdpClient中看不到任何實際數據包級類的原因是因為坦率地說它很簡單,因為它是一個無連接/無狀態協議。

數據包格式非常簡單

bits             0 – 15                   16 – 31
        +-----------------------+-------------------------+
0       | Source Port Number    | Destination Port Number |
        +-----------------------+-------------------------+
32      | Length                | Checksum                |
        +-----------------------+-------------------------+
64      |                                                 |
        |                      Data                       |
        |                                                 |
        +-------------------------------------------------+

另外,請注意校驗和計算實際上確實有點復雜

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM