2011-05-25 41 views
5

这是一种奇怪的请求。如何构造UDP数据包但不发送它

我有一个字节数组,我需要通过串行端口发送到另一个使用C#的设备。不过,我需要首先将字节数组包装在udp数据包中,但是它将再次通过串行端口发送,而不是通过udp发送。有没有办法构造一个udp数据包作为字节数组然后通过串口发送?

我已经使用udp之前发送和接收消息,但从未在udp数据包构建的位置发送消息,但未通过udp发送消息。

+0

所以你只需要IP层的数据包,而不是以太网包装? – 2011-05-25 14:36:52

+0

@Sam Skuce它需要IP和UDP头部,不知道IP头部是不是“以太网包装”,谢谢。 – Justin 2011-05-25 15:01:33

回答

1

我想我在.NET中看不到UdpClient中任何实际的数据包级别的原因是因为它是无连接/无状态的协议,因此坦率地说它很简单。

The packet format is crazy simple

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

Also, do note that the checksum computation does actually have a little bit of complexity to it

+3

如果你手工制作数据包,你还必须考虑到字节顺序。 – 2011-05-25 14:39:14

1

你应该可能创建包含在标准的UDP数据包的所有数据的UDP类构建你的UDP数据包。

数据作为follows

源端口[SP](16位):当尝试连接,或正在进行,这指定了端口的本地设备正在等待监听来自响应目标机器。

目标端口[DP](16位):当用户需要连接到远程计算机上的服务时,应用层程序将指定应使用的端口初始连接。当不作为初始连接的一部分时,这指定将数据包发送到其目的地时远程机器将使用的端口号。

Length [Len](16 bits):这允许接收站知道有多少传入比特应该是有效分组的一部分。长度是计算UDP数据包的多少个字节,包括头中的字节。由于UDP头中总是有4个字段,每个字段有16位,并且数据/有效载荷长度可变,所以我们知道长度将为8 +(有效载荷中的字节数)。

UDP Checksum [UDPCS ](16位):这是一个校验和,它覆盖UDP数据包的头部和数据部分,以允许接收主机验证传入UDP数据包的完整性。 UDP数据包在校验和字段中加载了一个预定义的数字,然后在计算校验和时,校验和被写入先前的数值。当数据包到达目的地时,目标机器的操作系统查找4头字段(由16到31位构成的字节),并将它们从数据包中提取出来,然后重新计算数据包上的校验和,而在校验和字段中没有任何内容。然后OS将计算出的校验和与数据包中传输的校验和进行比较。如果校验和相同,则数据正常,并允许通过,但如果有差异,UDP数据包和数据将被丢弃,并且接收机不会尝试获得新的数据复制,并且发送机器不会尝试发送相同的数据包。数据包永远丢失。 UDP不可靠!对于可靠的传输层TCP/IP套件协议,请参阅TCP数据包。

数据(可变位):如您所料,这是UDP数据包的有效载荷或数据部分。有效载荷可以是任何数量的协议(通常是应用层)。一些最常用的UDP协议包括NFS,DNS以及多音频和视频流协议。如果在UDP数据包中发生错误并且需要修复错误,则应用层会将其留给应用层以查找错误并请求其应用层“数据块”或“块”。

制作一个包含所有这些数据并适当填充它的类,重载ToString以允许您转换为Byte数组。

希望这会有所帮助。

2

我打算接受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; 
     } 
    } 

协议类:(太长,张贴在这里)

Protocol Class Code