如何构造UDP数据包但不发送

| 这有点奇怪。 我有一个字节数组,需要使用C#通过串行端口发送到另一个设备。但是,我需要先将字节数组包装在udp数据包中,但是同样,它将通过串行端口而不是通过udp发送。有没有一种方法可以将udp数据包构造为字节数组,然后通过串行端口发送? 我以前曾使用udp发送和接收消息,但从未在udp数据包的构造位置发送消息,但从未通过udp发送消息。     
已邀请:
C#原始UDP套接字程序示例     
我将接受Yochai的回答,因为该链接(以及该站点中的其他页面)提供了构建udp数据包和ip标头的代码。对于其他尝试实现此目标的人,下面是代码: 怎么称呼:
var udpPacketBytes = UDPPacket.Construct(IPAddress.Parse(\"1.1.1.1\"), 1000, IPAddress.Parse(\"2.2.2.2\"), 6100, payloadBytes);
UDPPacket类:
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;
        }
    }
协议类别:(太长,无法在此处发布) 协议类别代码     
您应该通过创建可能包含标准UDP数据包中所有数据的UDP类来构造UDP数据包。 数据如下: 源端口[SP](16位):尝试或进行连接时,它指定本地计算机正在等待侦听目标计算机响应的端口。 目标端口[DP](16位):当用户希望连接到远程计算机上的服务时,应用程序层程序将指定应使用的初始连接端口。当不作为初始连接的一部分时,此选项指定当将数据包发送到其目的地时,远程计算机将使用哪个端口号。 长度[长度](16位):这允许接收站知道应该将多少个输入位作为有效数据包的一部分。长度是对UDP数据包中包括报头中的字节的字节数的计算。由于UDP在标头中始终有4个字段,每个字段都有16位,并且数据/有效载荷的长度可变,因此我们知道长度为8 +(有效负载中的字节数)。 UDP校验和[UDPCS](16位):这是一个校验和,覆盖UDP数据包的标头和数据部分,以允许接收主机验证传入UDP数据包的完整性。 UDP数据包在校验和字段中加载了预定义的数字,然后在计算校验和时,将校验和写入先前的值。当数据包到达目的地时,目标计算机的操作系统将查找4头字段(从位16到31构成的字节)并将其从数据包中拉出,然后重新计算数据包中的校验和,而无需校验和字段。然后,操作系统将计算出的校验和与在数据包中传输的校验和进行比较。如果校验和相同,则数据可以通过,并且允许通过,但是如果存在差异,则UDP数据包和数据将被丢弃,并且接收计算机不会尝试获取新的复制,发送方机器将不会尝试发送相同的数据包。数据包永远丢失。 UDP不可靠!有关可靠的传输层TCP / IP套件协议,请参阅TCP数据包。 数据(可变位):就像您期望的那样,这是UDP数据包的有效负载或数据部分。有效负载可以是任意数量的协议(通常是应用程序层)。一些最常用的UDP协议包括NFS,DNS以及多种音频和视频流协议。如果UDP数据包中发生错误,并且希望修复错误,则将错误留给应用程序层以查找错误并请求其应用程序层“大块”或“大块”数据。 创建一个包含所有这些数据并适当填充的类,将使2过载,从而允许您转换为Byte数组。 希望这可以帮助。     
我想我之所以没有在.NET中的“ 3”中看到任何实际的数据包级类的原因,是因为坦率地说它非常简单,因为它是无连接/无状态协议。 数据包格式疯狂简单
bits             0 – 15                   16 – 31
        +-----------------------+-------------------------+
0       | Source Port Number    | Destination Port Number |
        +-----------------------+-------------------------+
32      | Length                | Checksum                |
        +-----------------------+-------------------------+
64      |                                                 |
        |                      Data                       |
        |                                                 |
        +-------------------------------------------------+
另外,请注意,校验和计算实际上确实有点复杂     

要回复问题请先登录注册