《TCP/IP详解,卷2:实现》读书笔记-以太网和IP

    我们先来回顾一下以太网帧的格式,以太网帧包括48bit的目标地址和源地址,接下来是一个16bit的类型字段,它标识这个帧所携带的数据的格式。对于IP分组,类型是0x0800(2048)。帧的最后是一个32bit的CRC(循环冗余检验),它用来检查帧中的差错。帧的格式如下图所示:

   

    我们用48bit的以太网地址作为硬件地址。IP地址到硬件地址之间的转换用ARP协议。而硬件地址到I P地址的转换用RARP协议。以太网地址有两种类型:单播和多播。一个单播地址描述一个单一的以太网接口,而一个多播地址描述一组以太网接口。一个以太网广播是一个所有接口都接收的多播。

    当一个完整的帧可用时,接口就产生一个中断,并且内核调用leintrleintr检测硬件,并且如果有一个帧到达,就调用leread把这个帧从接口转移到一个mbuf链中。如果硬件报告一个帧已传输完或发现一个差错(如一个有错误的检验和),则leintr更新相应的接口统计,复位这个硬件,并调用lestart来传输另一个帧。所有以太网设备驱动程序将它们接收到的帧传给ether_input做进一步的处理。设备驱动程序构造的mbuf链不包括以太网首部,以太网首部作为一个独立的参数传递给 ether_input

每个协议有它自己的地址格式。BSD在一个sockaddr结构中处理通用的地址。sa_len指示地址的长度(OSIUnix域协议有不同长度的地址)sa_family指示地址的类型。成员sa_lensa_family允许协议无关代码操作来自多个协议的变长的sockaddr结构。剩下的成员sa_data,包含一个协议相关格式的地址。sa_data定义为一个14字节的数组,但当sockaddr结构覆盖更大的内存空间时,sa_data可能会扩展到253字节。sa_len仅有一个字节,因此整个地址,包括sa_lensa_family必须不超过256字节。

这是C语言的一种通用技术,它允许程序员把一个结构中的最后一个成员看成是可变长的。

每个协议定义一个专用的sockaddr结构,该结构复制成员sa_lensa_family,但按那个协议的要求来定义成员sa_data。存储在sa_data中的地址是一个传输地址;它包含足够的信息来标识同一主机上的多个通信端点。在第6章我们要查看Internet地址结构sockaddr_in,它包含了一个IP地址和一个端口号。

    在以前的读书笔记中,描述了通用的sockaddrifaddr结构,很多做过socket编程的人对于这些结构 都比较陌生,因为这个是通过的结构,不仅仅IP协议会用到,其它协议也会用到,下面会讲到IP专用 的结构:sockaddr_inin_ifaddr。看到sockaddr_in,大家心中应该比较释然了,终于看到熟悉的结构了!
由于历史原因,BSD中以网络字节序将Internet地址存储在一个in_addr结构中。这个结
构只有一个成员s_addr,它包含这个地址。注意,一般为了方便本地对地址的处理,地址一般是以主机 字节序存储的,这里是一个例外。
    这里讲到字节序问题,我们引申一下,大概的介绍一下字节序的基本概念:

    字节序有两种,大端字节序和小端字节序,IntelX86系列芯片是小端字节序,IBMPowerPC芯片是大 端字节序,所谓本机字节序,本机使用什么芯片,本机字节序就对应芯片的字节序,网络字节序对应大端 字节序。对于数值0x1234,小端字节序0x12放在高地址,0x34放在低地址,大端字节序0x12放在低地址,0x34放在高地址。
  

struct in_addr {
    u_long s_addr;
};

struct sockaddr_in {
    u_char    sin_len;
    u_char    sin_family;
    u_short    sin_port;
    
struct    in_addr sin_addr;
    
char    sin_zero[8];
};


    in_ifaddr是为Internet协议定义的接口地址结构。对于每个指派给一个接口的IP地址,分配了一个in_ifaddr结构,并且添加到接口地址列表中和IP地址全局列表中。

struct in_ifaddr {
    
struct    ifaddr ia_ifa;        /* protocol-independent info */
#define    ia_ifp        ia_ifa.ifa_ifp
#define ia_flags    ia_ifa.ifa_flags
                    
/* ia_{,sub}net{,mask} in host order */
    u_long    ia_net;            
/* network number of interface */
    u_long    ia_netmask;        
/* mask of net part */
    u_long    ia_subnet;        
/* subnet number, including net */
    u_long    ia_subnetmask;        
/* mask of subnet part */
    
struct    in_addr ia_netbroadcast; /* to recognize net broadcasts */
    
struct    in_ifaddr *ia_next;    /* next in list of internet addresses */
    
struct    sockaddr_in ia_addr;    /* reserve space for interface name */
    
struct    sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */
#define    ia_broadaddr    ia_dstaddr
    
struct    sockaddr_in ia_sockmask; /* reserve space for general netmask */
    
struct    in_multi *ia_multiaddrs; /* list of multicast addresses */
};

struct    in_aliasreq {
    
char    ifra_name[IFNAMSIZ];        /* if name, e.g. "en0" */
    
struct    sockaddr_in ifra_addr;
    
struct    sockaddr_in ifra_broadaddr;
#define ifra_dstaddr ifra_broadaddr
    
struct    sockaddr_in ifra_mask;
};
    sin_len总是16(结构sockaddr_in的大小),并且sin_familyAF_INET
    sin_port是一个网络字节序(不是主机字节序)16bit值,用来分用运输层报文。
sin_addr 标识一个32bitInternet地址。 
    
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值