http://blog.chinaunix.net/uid-25909722-id-2779771.html
分类: LINUX
在学习了计算机网络的理论基础知识之后,如果能够对Linux下的TCP/IP实现代码进行一定的分析,将十分有利于加深对计算机网络理论的理解,同时能够使我们对网络既有理性的理解,也具有感性的认识。下面我们对Linux ubuntu 2.6.38-8-generic中的/usr/include/netinet/in.h文件结合网络理论进行一些分析。
- /* Standard well-defined IP protocols. */
- enum
- {
- IPPROTO_IP = 0, /* Dummy protocol for TCP. */
- #define IPPROTO_IP IPPROTO_IP
- IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
- #define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
- IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
- #define IPPROTO_ICMP IPPROTO_ICMP
- IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
- #define IPPROTO_IGMP IPPROTO_IGMP
- IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
- #define IPPROTO_IPIP IPPROTO_IPIP
- IPPROTO_TCP = 6, /* Transmission Control Protocol. */
- #define IPPROTO_TCP IPPROTO_TCP
- IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
- #define IPPROTO_EGP IPPROTO_EGP
- IPPROTO_PUP = 12, /* PUP protocol. */
- #define IPPROTO_PUP IPPROTO_PUP
- IPPROTO_UDP = 17, /* User Datagram Protocol. */
- #define IPPROTO_UDP IPPROTO_UDP
- IPPROTO_IDP = 22, /* XNS IDP protocol. */
- #define IPPROTO_IDP IPPROTO_IDP
- IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */
- #define IPPROTO_TP IPPROTO_TP
- IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
- #define IPPROTO_DCCP IPPROTO_DCCP
- IPPROTO_IPV6 = 41, /* IPv6 header. */
- #define IPPROTO_IPV6 IPPROTO_IPV6
- IPPROTO_ROUTING = 43, /* IPv6 routing header. */
- #define IPPROTO_ROUTING IPPROTO_ROUTING
- IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
- #define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
- IPPROTO_RSVP = 46, /* Reservation Protocol. */
- #define IPPROTO_RSVP IPPROTO_RSVP
- IPPROTO_GRE = 47, /* General Routing Encapsulation. */
- #define IPPROTO_GRE IPPROTO_GRE
- IPPROTO_ESP = 50, /* encapsulating security payload. */
- #define IPPROTO_ESP IPPROTO_ESP
- IPPROTO_AH = 51, /* authentication header. */
- #define IPPROTO_AH IPPROTO_AH
- IPPROTO_ICMPV6 = 58, /* ICMPv6. */
- #define IPPROTO_ICMPV6 IPPROTO_ICMPV6
- IPPROTO_NONE = 59, /* IPv6 no next header. */
- #define IPPROTO_NONE IPPROTO_NONE
- IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
- #define IPPROTO_DSTOPTS IPPROTO_DSTOPTS
- IPPROTO_MTP = 92, /* Multicast Transport Protocol. */
- #define IPPROTO_MTP IPPROTO_MTP
- IPPROTO_ENCAP = 98, /* Encapsulation Header. */
- #define IPPROTO_ENCAP IPPROTO_ENCAP
- IPPROTO_PIM = 103, /* Protocol Independent Multicast. */
- #define IPPROTO_PIM IPPROTO_PIM
- IPPROTO_COMP = 108, /* Compression Header Protocol. */
- #define IPPROTO_COMP IPPROTO_COMP
- IPPROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
- #define IPPROTO_SCTP IPPROTO_SCTP
- IPPROTO_UDPLITE = 136, /* UDP-Lite protocol. */
- #define IPPROTO_UDPLITE IPPROTO_UDPLITE
- IPPROTO_RAW = 255, /* Raw IP packets. */
- #define IPPROTO_RAW IPPROTO_RAW
- IPPROTO_MAX
- };
很显然,上面的代码定义了所以基于IP协议的一些协议的枚举。
其中为我们大多数人熟知的协议如下:
1. IPPROTO_ICMP = 1,
/* Internet Control Message Protocol. */
该协议简写为ICMP,即
Internet控制报文协议,著名的ping命令就是利用该协议来实现的。
2. IPPROTO_TCP = 6, /* Transmission Control Protocol. */
TCP协议,即传输层控制协议。
3. IPPROTO_UDP = 17, /* User Datagram Protocol. */
UDP协议,即用户数据报协议。
4. IPPROTO_MTP = 92, /* Multicast Transport Protocol. */
多播传输协议。
还有它们对应的IPv6的协议。
- /* Type to represent a port. */
- typedef uint16_t in_port_t;
- /* Standard well-known ports. */
- enum
- {
- IPPORT_ECHO = 7, /* Echo service. */
- IPPORT_DISCARD = 9, /* Discard transmissions service. */
- IPPORT_SYSTAT = 11, /* System status service. */
- IPPORT_DAYTIME = 13, /* Time of day service. */
- IPPORT_NETSTAT = 15, /* Network status service. */
- IPPORT_FTP = 21, /* File Transfer Protocol. */
- IPPORT_TELNET = 23, /* Telnet protocol. */
- IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */
- IPPORT_TIMESERVER = 37, /* Timeserver service. */
- IPPORT_NAMESERVER = 42, /* Domain Name Service. */
- IPPORT_WHOIS = 43, /* Internet Whois service. */
- IPPORT_MTP = 57,
-
- IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */
- IPPORT_RJE = 77,
- IPPORT_FINGER = 79, /* Finger service. */
- IPPORT_TTYLINK = 87,
- IPPORT_SUPDUP = 95, /* SUPDUP protocol. */
-
-
- IPPORT_EXECSERVER = 512, /* execd service. */
- IPPORT_LOGINSERVER = 513, /* rlogind service. */
- IPPORT_CMDSERVER = 514,
- IPPORT_EFSSERVER = 520,
-
- /* UDP ports. */
- IPPORT_BIFFUDP = 512,
- IPPORT_WHOSERVER = 513,
- IPPORT_ROUTESERVER = 520,
-
- /* Ports less than this value are reserved for privileged processes. */
- IPPORT_RESERVED = 1024,
-
- /* Ports greater this value are reserved for (non-privileged) servers. */
- IPPORT_USERRESERVED = 5000
- };
typedef uint16_t in_port_t;定义了端口为一个16位的无符号整数。
接下来的enum定义了一些系统常用的端口号。
IPPORT_NETSTAT = 15,
/* Network status service. */ 提供netstat命令行服务的端口号
IPPORT_FTP = 21,
/* File Transfer Protocol. */ FTP使用的端口号
IPPORT_TELNET = 23, /* Telnet protocol. */ 提供telent命令行服务的端口号
IPPORT_SMTP = 25,
/* Simple Mail Transfer Protocol. */ 简单邮件协议的端口号
IPPORT_NAMESERVER = 42, /* Domain Name Service. */ DNS的端口号
/* Ports less than this value are reserved for privileged processes. */
IPPORT_RESERVED = 1024,
所以小于1024的端口号是系统预用的端口号。
- /* Internet address. */
- typedef uint32_t in_addr_t;
- struct in_addr
- {
- in_addr_t s_addr;
- };
上面的结构定义了IP地址,为一个32位的无符号整数。
- /* Definitions of the bits in an Internet address integer.
- On subnets, host and network parts are found according to
- the subnet mask, not these masks.
- */
- #define IN_CLASSA(a) ((((in_addr_t)(a)) & 0x80000000) == 0)
- #define IN_CLASSA_NET 0xff000000
- #define IN_CLASSA_NSHIFT 24
- #define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
- #define IN_CLASSA_MAX 128
-
- #define IN_CLASSB(a) ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000)
- #define IN_CLASSB_NET 0xffff0000
- #define IN_CLASSB_NSHIFT 16
- #define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
- #define IN_CLASSB_MAX 65536
-
- #define IN_CLASSC(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000)
- #define IN_CLASSC_NET 0xffffff00
- #define IN_CLASSC_NSHIFT 8
- #define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
-
- #define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000)
- #define IN_MULTICAST(a) IN_CLASSD(a)
-
- #define IN_EXPERIMENTAL(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000)
- #define IN_BADCLASS(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000)
-
- /* Address to accept any incoming messages. */
- #define INADDR_ANY ((in_addr_t) 0x00000000)
- /* Address to send to all hosts. */
- #define INADDR_BROADCAST ((in_addr_t) 0xffffffff)
- /* Address indicating an error return. */
- #define INADDR_NONE ((in_addr_t) 0xffffffff)
-
- /* Network number for local host loopback. */
- #define IN_LOOPBACKNET 127
- /* Address to loopback in software to local host. */
- #ifndef INADDR_LOOPBACK
- # define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) /* Inet 127.0.0.1. */
- #endif
-
- /* Defines for Multicast INADDR. */
- #define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) /* 224.0.0.0 */
- #define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) /* 224.0.0.1 */
- #define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */
- #define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */
#define IN_CLASSA(a)
((((in_addr_t)(a)) & 0x80000000) == 0)
#define IN_CLASSB(a) ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000)
#define IN_CLASSC(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000)
#define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000)
#define IN_EXPERIMENTAL(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000)
#define IN_BADCLASS(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000)
该宏用于判断一个IP地址是否是一个A类地址,因为我们知道:
A类地址的最高位为:0
B类地址的最高位为:10
C类地址的最高位为:110
D类地址的最高位为:1110
这几个宏分别:
提起IP地址的最高1位,如果最高位是0,则是A类IP地址
提起IP地址的最高2位,如果最高2位是10,则是B类IP地址
提起IP地址的最高3位,如果最高3位是110,则是C类IP地址
提起IP地址的最高4位,如果最高4位是1110,则是D类IP地址
#define
IN_CLASSA_NET
0xff000000
用于提起A类IP地址的网络地址部分。
#define
IN_CLASSA_NSHIFT
24
定义了A类IP地址的网络地址部分开始的偏移为24.(24--31位)
#define
IN_CLASSA_HOST
(0xffffffff & ~IN_CLASSA_NET)
用于提起A类IP地址的主机地址部分。
#define
IN_CLASSA_MAX
128
定义了A类IP地址允许有128个子网(2的7次方等于128)。
其他关于B、C、D类地址的相关定义类似。
/* Address to accept any incoming messages. */
#define
INADDR_ANY
((in_addr_t) 0x00000000)
该宏定义的IP地址可以接收所有发送过来的数据包。
/* Address to send to all hosts. */
#define
INADDR_BROADCAST
((in_addr_t) 0xffffffff)
该宏定义了“有限广播地址”或者称为“本地网广播地址”,它用于在
本地子网中进行广播。因为它的32位全部为1,所以它不可能去表示一个IP地址的网络地址部分,所以它只能用于本地子网进行广播。我们还有另外一种广播形式成为“定向广播”,它由某个Internate子网的网络部分加上全1的主机地址组成,可以用于定向向该Internate子网中的所有的主机进行广播,因为它可以指定向某个子网进行广播,所以叫“定向广播”。
/* Network number for local host loopback. */
#define
IN_LOOPBACKNET
127
定义了本地回网的
网络地址部分。
/* Address to loopback in software to local host. */
#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBACK
((in_addr_t) 0x7f000001) /* Inet 127.0.0.1. */
#endif
定义了本地回网的IP地址。
/* Defines for Multicast INADDR. */
#define INADDR_UNSPEC_GROUP
((in_addr_t) 0xe0000000) /* 224.0.0.0 */
#define INADDR_ALLHOSTS_GROUP
((in_addr_t) 0xe0000001) /* 224.0.0.1 */
#define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */
#define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */
这些宏定义了相关的组播地址。
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
定义了IPv4的IP地址的长度为16个字节,IPv6的IP地址长度为46字节。
- /* Structure describing an Internet socket address. */
- struct sockaddr_in
- {
- __SOCKADDR_COMMON (sin_);
- in_port_t sin_port; /* Port number. */
- struct in_addr sin_addr; /* Internet address. */
-
- /* Pad to size of `struct sockaddr'. */
- unsigned char sin_zero[sizeof (struct sockaddr) -
- __SOCKADDR_COMMON_SIZE -
- sizeof (in_port_t) -
- sizeof (struct in_addr)];
- };
定义了表示IP地址的结构体。显然该结构体的大小和struct sockaddr的大小一样。
- /* IPv4 multicast request. */
- struct ip_mreq
- {
- /* IP multicast address of group. */
- struct in_addr imr_multiaddr;
-
- /* Local IP address of interface. */
- struct in_addr imr_interface;
- };
-
- struct ip_mreq_source
- {
- /* IP multicast address of group. */
- struct in_addr imr_multiaddr;
-
- /* IP address of source. */
- struct in_addr imr_interface;
-
- /* IP address of interface. */
- struct in_addr imr_sourceaddr;
- };
定义了组播相关的结构体。