This is sort of an odd request.
I have a byte array that I need to send over serial port to another device using C#. However I need to first wrap the byte array within a udp packet, but again, it's going to be sent via serial port, not via udp. Is there a way to construct a udp packet as an array of bytes to then send over the serial port?
I've sent and received messages using udp before but never where the udp packet is constructed but not sent via udp.
UDP is completely stateless, so after firing off a packet the only way an application can expect a response is if it knows the other end is going to send one.
Now, since UDP is a connection-less protocol so unlike TCP, UDP server will not send response over some connection, instead, UDP server will extract the source IP address and source port from the request and send the response back to client.
The communication protocol just sends the packets, which means it has much lower bandwidth overhead and latency. With UDP, packets may take different paths between sender and receiver. As a result, some packets may be lost or received out of order.
UDP does not guarantee that transmitted packets will be received in any particular order, although the underlying protocols such as IP imply that packets will generally be received in the order transmitted in the absence of routing and/or hardware errors. TCP places no limits on the size of transmitted data.
C# Raw UDP Socket Program Example
I'm going to accept Yochai's answer, as that link (and other pages within that site) provided the code to build both the udp packet and the ip header. For others trying to accomplish it, here is the code:
How to call it:
var udpPacketBytes = UDPPacket.Construct(IPAddress.Parse("1.1.1.1"), 1000, IPAddress.Parse("2.2.2.2"), 6100, payloadBytes);
UDPPacket 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;
}
}
Protocol classes: (too long to post here)
Protocol Class Code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With