这是一种奇怪的请求。如何构造UDP数据包但不发送它
我有一个字节数组,我需要通过串行端口发送到另一个使用C#的设备。不过,我需要首先将字节数组包装在udp数据包中,但是它将再次通过串行端口发送,而不是通过udp发送。有没有办法构造一个udp数据包作为字节数组然后通过串口发送?
我已经使用udp之前发送和接收消息,但从未在udp数据包构建的位置发送消息,但未通过udp发送消息。
这是一种奇怪的请求。如何构造UDP数据包但不发送它
我有一个字节数组,我需要通过串行端口发送到另一个使用C#的设备。不过,我需要首先将字节数组包装在udp数据包中,但是它将再次通过串行端口发送,而不是通过udp发送。有没有办法构造一个udp数据包作为字节数组然后通过串口发送?
我已经使用udp之前发送和接收消息,但从未在udp数据包构建的位置发送消息,但未通过udp发送消息。
我想我在.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
如果你手工制作数据包,你还必须考虑到字节顺序。 – 2011-05-25 14:39:14
你应该可能创建包含在标准的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数组。
希望这会有所帮助。
我打算接受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;
}
}
协议类:(太长,张贴在这里)
所以你只需要IP层的数据包,而不是以太网包装? – 2011-05-25 14:36:52
@Sam Skuce它需要IP和UDP头部,不知道IP头部是不是“以太网包装”,谢谢。 – Justin 2011-05-25 15:01:33