我有一个小函数,它尝试打印IP报头的片段偏移量。
ParseIpHeader(unsigned char *packet, int len)
{
struct ethhdr *ethernet_header;
struct iphdr *ip_header;
/* First Check if the packet contains an IP header using
the Ethernet header */
ethernet_header = (struct ethhdr *)packet;
if(ntohs(ethernet_header->h_proto) == ETH_P_IP)
{
/* The IP header is after the Ethernet header */
if(len >= (sizeof(struct ethhdr) + sizeof(struct iphdr)))
{
ip_header = (struct iphdr*)(packet + sizeof(struct ethhdr));
/* print the Source and Destination IP address */
//printf("Dest IP address: %s\n", inet_ntoa(ip_header->daddr));
//printf("Source IP address: %s\n", inet_ntoa(ip_header->saddr));
printf("protocol %d\n", ip_header->protocol);
printf("Fragment off is %d\n", ntohs(ip_header->frag_off));
}
}我的数据包是TCP (ip_header->协议总是6。问题是frag_off总是16384。我发送了很多数据,为什么frag_off总是不变?
谢谢。
发布于 2010-02-22 05:51:09
片段偏移量与标志共享。您设置了"DF“(不分割)位。
假设片段偏移量为0,则整个16位字段的值为16384。
从第10页开始,看看http://www.ietf.org/rfc/rfc791.txt。
编辑
您正在接收的TCP数据段中的DF位由远程端设置,以执行Path MTU discovery --简而言之,就是试图避免碎片。在这种情况下,发送端获知整个路径可以处理的最大MTU,并截断TCP数据段,使其在封装成IP后不会超过该MTU。
EDIT2
关于recvfrom()和TCP的使用:TCP是一个面向连接的协议,所有的分段/分段细节都已经由它处理了(分段显然是由较低层IP处理的)-所以您不需要处理它。您在发送端写入()的任何内容最终都将在另一端读取()-可能是而不是在相同的区块中-即两次4K写入有时可能导致一次8K读取,有时可能导致两次4K读取-这取决于中间介质关于重新排序/丢失的行为。
IP分片和重组是由操作系统透明处理的,因此您不需要担心它,就像处理数据包乱序等问题一样(您只会看到性能下降对应用程序的影响)。
我可以推荐的一本好书是:UNIX network programming。考虑到Steven与TCP的关系,无论您使用哪种操作系统,这都是一本好书。
EDIT3:
如果你正在做一些事情来成为“中间人”(假设你有好的和合法的理由这样做:-) -那么你可以通过查看现有技术来评估即将到来的工作:chaosreader (在pcap文件上工作的单脚本方法,但可以适应其他东西),或者LibNIDS -它确实模拟了IP碎片整理和TCP流重组;并且可能只是为了你的目的而重用它们。
https://stackoverflow.com/questions/2307531
复制相似问题