《TCP/IP 详解卷2》代码疑点解析

图8-28

#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}

这段代码的意图是把高16位的值加到低16位上,但是通过减去 65535 就能达到相同的目的吗?图8-27的代码就比较符合直觉:

sum = (sum & 0xFFFF) + (sum >> 16);

通过一个示例来验证下图8-28的代码能否实现对应的意图:

#include <stdio.h>

union {
    unsigned short s[2];
    int            l;
} l_util;

int main()
{
    l_util.s[0] = 0xF800;
    l_util.s[1] = 0xF500;

    printf( "%x\n", l_util.l );

    int sum = l_util.s[0] + l_util.s[1];
    printf( "%x\n", sum );

    sum > 65535 ? sum -= 65535 : sum;
    printf( "%x\n", sum );

    return 0;
}

编译运行结果为:

[[email protected] test]$ ./test
f500f800
1ed00
ed01
[[email protected] test]$ 

结果是正确的!

减去 65535 实际上就是加上 -65535 的补码:FFFF0001 。两个 unsigned short 型的整数相加,只能产生一个进位,所以当 x > 65535 时就相当于:

x - 65535 = x + FFFF0001 = 0001**** + FFFF0001 = 0000**** + 00000001

时间: 2024-10-14 17:15:33

《TCP/IP 详解卷2》代码疑点解析的相关文章

《TCP/IP详解卷1:协议》第5章 RARP:逆地址解析协议-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 1.引言 具有本地磁盘的系统引导

《TCP/IP详解卷2:实现》笔记--IP的分片和重装

IP首部内有三个字段实现分片和重装:标识字段(ip_id).标志字段(ip_off的3个高位比特)和偏移字段(ip_off的13个低位 比特).标志字段由3个1bit标志组成.比特0是保留的必须为0,:比特1是"不分片"(DF)标志:比特2是"更多分片"(MF)标志. Net/3中,标志和偏移字段结合起来,由ip_off访问,如下图所示: ip_off的其他13bit指出在原始数据报内分片的位置,以8字节为单位计算.因此,除最后一个分片外,其他的分片都希望是一个 8

《TCP/IP详解卷2:实现》笔记--IP编址

1.接口和地址 在本文中讨论的所有接口和地址结构的一个例子配置如下图所示: 上图中显示了我们三个接口例子:以太网接口,SLIP接口和环回接口.它们都有一个链路层地址作为地址列表中的第一个结点. 显示的以太网接口有两个IP地址,SLIP接口有一个IP地址,并且环回接口有一个IP地址和一个OSI地址. 所有的IP地址都被链接到in_ifaddr列表中,并且所有链路层地址能从ifnet_addrs数组访问. 后面的部分讨论上图的数据结构以及用来查看和修改这些结构的IP专用ioctl命令. 2.sock

《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协

《TCP/IP详解卷2:实现》笔记--IP:网际协议

本章介绍IP分组的结构和基本的IP处理过程,包括输入,转发和输出.下图显示了IP层常见的组织形式. 在之前的文章中,我们看到了网络接口如何把到达的IP分组放到IP输入队列ipintrq中去,并如何调用一个软件中断,如下图所示: 因为硬件中断的优先级比软件中断的要高,所以在发生一次软件中断之前,有的分组可能会被放到队列中.在软件中断中,ipintr 函数不断从ipintrq中移走和处理分组,直到对垒为空.在最终的目的地,IP把分组重装为数据包,并通过函数调用把该数据包直接 传给适当的运输层协议.如

《TCP/IP详解卷2:实现》笔记--IGMP:Internet组管理协议

IGMP在本地网络上的主机和路由器之间传达组成员信息,路由器定时向所有主机组多播IGMP查询.主机多播IGMP报告报文 以响应查询. 从体系结构的观点来看,IGMP是位于IP上面的运输层协议.它有一个协议号(2),它的报文是由IP数据报承载的.与ICMP 一样,进程通常不直接访问IGMP,但进程可以通过IGMP插口发送和接受IGMP报文.这个特性使得能够把多播选路守护程序 作为用户级进程实现. 下图是Net/3中IGMP协议的整体结构: 到达的IGMP查询使igmp_input为每个in_mul

《TCP/IP详解卷2:实现》笔记--中断级别与并发

网络代码处理输入分组用的是异步和中断驱动的方式.首先,一个设备中断引发接口层代码执行,然后它产生一个软中断 引发协议层代码执行.当内核完成这些级别的中断后,执行插口代码.当内核完成这些级别的中断后,执行插口代码. 在这里给每个硬件和软件中断分配一个优先级.如下图: 对于不同优先级,一个要关心的问题就是如何处理那些在不同级别的进程共享的数据结构.例如,当IP输入例程正在从它的 输入队列中取出一个接收的分组时,一个设备中断发生,抢占了协议层,并且那个设备驱动程序可能添加一个分组到IP输入 队列.这些

《TCP/IP详解卷1:协议》第14章 DNS:域名系统---读书笔记

<TCP/IP详解卷1:协议>第14章 DNS:域名系统---读书笔记 1.引言 5.指针查询 DNS中一直难于理解的部分就是指针查询方式,即给定一个IP地址,返回与该地址对应的域名. 当一个组织加入Internet,并获得DNS域名空间的授权,如noao.edu,则它们也获得了对应IP地址的in-addr.arpa域名空间的授权.在noao.edu这个例子中,它的网络号是140.252的B类网络.在DNS树中结点in-addr.arpa的下一级必须是该IP地址的第一字节(例中为140),再下

《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协

《TCP/IP详解卷1:协议》第3章 IP:网际协议(1)-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 1.引言 IP是TCP/IP协议族中最核心的协议.所有的TCP.UDP.ICMP及IGMP数据都以IP数据报格式传输.IP提供不可靠.无连接的数据报传送服务. (1)不可靠 它不能保证IP数据报能成功地到达目的地.IP仅提供最好的传输服务.如果发生某种错误,如某个路由器暂时用完了缓冲区,IP有一个简单的错误处理算法:丢弃该数据报,然后发送ICMP消息报给信源端.