2011-05-25 71 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