这是一个奇怪的请求。
我有一个字节数组,需要通过串口发送给另一个使用C#的设备。然而,我需要首先将字节数组包装在udp数据包中,但同样,它将通过串口发送,而不是通过udp。是否可以将udp数据包构造为字节数组,然后通过串行端口发送?
我以前使用udp发送和接收过消息,但从来没有在构造udp数据包但不通过udp发送的地方。
发布于 2011-05-25 22:34:04
发布于 2011-05-26 00:00:17
我将接受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
发布于 2011-05-25 22:34:24
您应该通过创建一个包含标准UDP数据包中包含的所有数据的UDP类来构造UDP数据包。
数据为follows格式
源端口SP:当尝试或正在进行连接时,它指定本地计算机正在等待哪个端口来侦听来自目标计算机的响应。
目的端口DP:当用户想要连接到远程机器上的服务时,应用层程序指定初始连接应该使用哪个端口。如果不是初始连接的一部分,则指定在将数据包发送到其目的地时将用于远程计算机的端口号。
Length Len:这允许接收站知道多少传入比特被认为是有效分组的一部分。长度是UDP数据包的一部分有多少字节的计算,包括报头中的字节。由于UDP在报头中总是有4个字段,并且每个字段都有16位,并且数据/有效载荷的长度可变,因此我们知道长度将是8+(有效载荷中的字节数)。
UDP Checksum UDPCS:这是一种校验和,它覆盖了数据包的报头和数据部分,允许接收主机验证传入的UDP数据包的完整性。UDP数据包在校验和字段中加载一个预定义的数字,然后在计算校验和时,校验和将覆盖先前的值。当数据包到达目的地时,目标机器的操作系统查看4个报头字段(从第16位到第31位产生的字节),并将它们从数据包中取出,然后重新计算数据包的校验和,而校验和字段中没有任何内容。然后,OS将计算出的校验和与数据包中传输的校验和进行比较。如果校验和相同,则数据没有问题,并允许其继续传递,但如果存在差异,则会丢弃UDP数据包和数据,并且接收机器不会尝试获取新的副本,发送机器也不会尝试发送相同的数据包。数据包将永远丢失。UDP不可靠!有关可靠的传输层TCP/IP协议簇协议,请参阅TCP数据包。
UDP (Variable bits):如您所料,这是数据包的有效载荷或数据部分。有效负载可以是任意数量的协议(通常是应用层)。一些最常用的UDP协议包括NFS、DNS以及多个音频和视频流协议。如果在UDP分组中出现错误并且希望修复错误,则留给应用层来查找错误并请求其应用层的“块”或“块”数据。
创建一个包含所有这些数据并适当填充它的类,重载ToString以允许您随后转换为字节数组。
希望这能有所帮助。
https://stackoverflow.com/questions/6126012
复制相似问题