2011-05-25 8 views
5

Esto es una especie de solicitud extraña.Cómo construir un paquete UDP pero no enviarlo

Tengo una matriz de bytes que necesito enviar a través de un puerto serie a otro dispositivo usando C#. Sin embargo, primero necesito envolver la matriz de bytes dentro de un paquete udp, pero de nuevo, se enviará a través del puerto serie, no a través de udp. ¿Hay alguna forma de construir un paquete udp como una matriz de bytes para luego enviarlos a través del puerto serie?

He enviado y recibido mensajes utilizando udp antes pero nunca donde se construye el paquete udp pero no se envió a través de udp.

+0

¿Entonces solo necesita el paquete de capa IP, no las envolturas de Ethernet? –

+0

@Sam Skuce Necesitaría tanto el encabezado IP como el encabezado UDP, no estoy seguro si el encabezado IP es el "envoltorio Ethernet" o no, gracias. – Justin

Respuesta

1

Supongo que la razón por la que no veo ninguna clase de paquete de nivel real en el UdpClient en .NET es porque francamente es muy simple porque es un protocolo sin conexión/sin estado.

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

También debe tener en cuenta la endianidad si está creando manualmente los paquetes. –

1

Usted debe construir su paquete UDP tal vez por la creación de una clase UDP que contiene todos los datos contenidos en un paquete UDP estándar.

de datos es tan follows:

Puerto de origen [SP] (16 bits): Cuando se intenta realizar una conexión, o llevando a cabo, esto especifica qué puerto la máquina local está a la espera de escuchar las respuestas de la máquina de destino

Puerto de destino [DP] (16 bits): Cuando un usuario desea conectarse a un servicio en una máquina remota, el programa de capa de aplicación especifica qué conexiones iniciales de puerto deberían usar. Cuando no forma parte de una conexión inicial, esto especifica qué número de puerto se utilizará para la máquina remota a medida que se envía un paquete a su destino.

Longitud [Len] (16 bits): Esto permite que la estación receptora saber cuántos de los bits de entrada se supone que son parte de un paquete válido. La longitud es un cálculo de cuántos bytes son parte del paquete UDP, incluidos los bytes en el encabezado. Desde UDP siempre tiene 4 campos en la cabecera y cada uno tiene 16 bits, y los datos/carga útil de longitud variable, que saber la longitud será de 8 + (número de bytes en la carga útil.)

UDP Checksum [UDPCS ] (16 bits): Esta es una suma de comprobación que cubre el encabezado y la porción de datos de un paquete UDP para permitir que el host receptor verifique la integridad de un paquete UDP entrante. El paquete UDP se carga con un número predefinido en el campo de suma de comprobación, y luego cuando se calcula la suma de comprobación, la suma de comprobación se escribe sobre el valor anterior. Cuando el paquete llega al destino, el sistema operativo de la máquina de destino mira al campo de encabezado 4 (bytes hechos desde los bits 16 al 31) y los saca del paquete, luego vuelve a calcular la suma de comprobación en el paquete sin nada en el campo de suma de comprobación . Luego, el sistema operativo compara la suma de control calculada con la que se transmitió en el paquete. Si la suma de comprobación es la misma, los datos están bien, y se permite pasar, pero si hay una diferencia, el paquete UDP y los datos se descartan, y la máquina receptora no intenta obtener un nuevo copiar, y la máquina de envío no intentará enviar ese mismo paquete. El paquete se pierde para siempre. ¡UDP no es confiable! Para obtener un protocolo de suite TCP/IP de Capa de transporte confiable, vea el paquete TCP.

Datos (bits variables): Como era de esperar, esta es la parte de carga o datos de un paquete UDP. La carga útil puede ser cualquier cantidad de protocolos (a menudo capa de aplicación). Algunos de los protocolos UDP más utilizados incluyen NFS, DNS, así como también múltiples protocolos de transmisión de audio y video. Si se produce un error en un paquete UDP y se desea corregir un error, se deja que la capa de aplicación encuentre el error y solicite a su capa de aplicación "trozo" o "trozo" de datos.

Haciendo una clase que contenga todos estos datos y los rellene apropiadamente, se sobrecarga ToString para permitirle convertir a la matriz de bytes.

Espero que esto ayude.

2

Voy a aceptar la respuesta de Yochai, ya que ese enlace (y otras páginas dentro de ese sitio) proporcionan el código para compilar tanto el paquete udp como el encabezado ip. Para otros tratando de lograrlo, aquí está el código:

cómo llamarlo: Clase

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; 
     } 
    } 

clases de protocolo: (demasiado tiempo para publicar aquí)

Protocol Class Code

Cuestiones relacionadas