Linux网络编程--7. TCP/IP协议

190 篇文章 1 订阅
 你也许听说过TCP/IP 协议 ,那么你知道到底什么是TCP,什么是IP吗?在这一章里面,我们一起来学习这个目前网络上用最广泛的 协议
  
  7.1 网络传输分层 
  如果你考过计算机等级考试,那么你就应该已经知道了网络传输分层这个概念.在网络上,人们为了传输数据时的方便,把网络的传输分为7个层次.分别是:应用层,表示层,会话层,传输层,网络层,数据链路层和物理层.分好了层以后,传输数据时,上一层如果要数据的话,就可以直接向下一层要了,而不必要管数据传输的细节.下一层也只向它的上一层提供数据,而不要去管其它东西了.如果你不想考试,你没有必要去记这些东西的.只要知道是分层的,而且各层的作用不同. 
  
  7.2 IP协议 
  IP协议是在网络层的协议.它主要完成数据包的发送作用. 下面这个表是IP4的数据包格式 
  
  0 4 8 16 32 
  -------------------------------------------------- 
  |版本 |首部长度|服务类型| 数据包总长 | 
  -------------------------------------------------- 
  | 标识 |DF |MF| 碎片偏移 | 
  -------------------------------------------------- 
  | 生存时间 | 协议 | 首部较验和 | 
  ------------------------------------------------ 
  | 源IP地址 | 
  ------------------------------------------------ 
  | 目的IP地址 | 
  ------------------------------------------------- 
  | 选项 | 
  ================================================= 
  | 数据 | 
  ------------------------------------------------- 
  
  下面我们看一看IP的结构定义 
  
  struct ip 
  { 
  #if __BYTE_ORDER == __LITTLE_ENDIAN 
  unsigned int ip_hl:4; /* header length */ 
  unsigned int ip_v:4; /* version */ 
  #endif 
  #if __BYTE_ORDER == __BIG_ENDIAN 
  unsigned int ip_v:4; /* version */ 
  unsigned int ip_hl:4; /* header length */ 
  #endif 
  u_int8_t ip_tos; /* type of service */ 
  u_short ip_len; /* total length */ 
  u_short ip_id; /* identification */ 
  u_short ip_off; /* fragment offset field */ 
  #define IP_RF 0x8000 /* reserved fragment flag */ 
  #define IP_DF 0x4000 /* dont fragment flag */ 
  #define IP_MF 0x2000 /* more fragments flag */ 
  #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 
  u_int8_t ip_ttl; /* time to live */ 
  u_int8_t ip_p; /* protocol */ 
  u_short ip_sum; /* checksum */ 
  struct in_addr ip_src, ip_dst; /* source and dest address */ 
  }; 
  
  ip_vIP协议的版本号,这里是4,现在IPV6已经出来了 
  
  ip_hlIP包首部长度,这个值以4字节为单位.IP协议首部的固定长度为20个字节,如果IP包没有选项,那么这个值为5. 
  
  ip_tos服务类型,说明提供的优先权. 
  
  ip_len说明IP数据的长度.以字节为单位. 
  
  ip_id标识这个IP数据包. 
  
  ip_off碎片偏移,这和上面ID一起用来重组碎片的. 
  
  ip_ttl生存时间.没经过一个路由的时候减一,直到为0时被抛弃. 
  
  ip_p协议,表示创建这个IP数据包的高层协议.如TCP,UDP协议. 
  
  ip_sum首部校验和,提供对首部数据的校验. 
  
  ip_src,ip_dst发送者和接收者的IP地址 
  
  关于IP协议的详细情况,请参考 RFC791 
  
  7.3 ICMP协议 
  ICMP是消息控制协议,也处于网络层.在网络上传递IP数据包时,如果发生了错误,那么就会用ICMP协议来报告错误. 
  
  ICMP包的结构如下: 
  
  0 8 16 32 
  --------------------------------------------------------------------- 
  | 类型 | 代码 | 校验和 | 
  -------------------------------------------------------------------- 
  | 数据 | 数据 | 
  -------------------------------------------------------------------- 
  
  ICMP在中的定义是 
  struct icmphdr 
  { 
  u_int8_t type; /* message type */ 
  u_int8_t code; /* type sub-code */ 
  u_int16_t checksum; 
  union 
  { 
  struct 
  { 
  u_int16_t id; 
  u_int16_t sequence; 
  } echo; /* echo datagram */ 
  u_int32_t gateway; /* gateway address */ 
  struct 
  { 
  u_int16_t __unused; 
  u_int16_t mtu; 
  } frag; /* path mtu discovery */ 
  } un; 
  }; 
  
  关于ICMP协议的详细情况可以查看 RFC792 
  
  7.4 UDP协议 
  UDP协议是建立在IP协议基础之上的,用在传输层的协议.UDP和IP协议一样是不可靠的数据报服务.UDP的头格式为: 
  
  0 16 32 
  --------------------------------------------------- 
  | UDP源端口 | UDP目的端口 | 
  --------------------------------------------------- 
  | UDP数据报长度 | UDP数据报校验 | 
  --------------------------------------------------- 
  
  UDP结构在中的定义为: 
  struct udphdr { 
  u_int16_t source; 
  u_int16_t dest; 
  u_int16_t len; 
  u_int16_t check; 
  }; 
  
  关于UDP协议的详细情况,请参考 RFC768 
  7.5 TCP 
  TCP协议也是建立在IP协议之上的,不过TCP协议是可靠的.按照顺序发送的.TCP的数据结构比前面的结构都要复杂. 
  
  0 4 8 10 16 24 32 
  ------------------------------------------------------------------- 
  | 源端口 | 目的端口 | 
  ------------------------------------------------------------------- 
  | 序列号 | 
  ------------------------------------------------------------------ 
  | 确认号 | 
  ------------------------------------------------------------------ 
  | | |U|A|P|S|F| | 
  |首部长度| 保留 |R|C|S|Y|I| 窗口 | 
  | | |G|K|H|N|N| | 
  ----------------------------------------------------------------- 
  | 校验和 | 紧急指针 | 
  ----------------------------------------------------------------- 
  | 选项 | 填充字节 | 
  ----------------------------------------------------------------- 
  
  TCP的结构在中定义为: 
  struct tcphdr 
  { 
  u_int16_t source; 
  u_int16_t dest; 
  u_int32_t seq; 
  u_int32_t ack_seq; 
  #if __BYTE_ORDER == __LITTLE_ENDIAN 
  u_int16_t res1:4; 
  u_int16_t doff:4; 
  u_int16_t fin:1; 
  u_int16_t syn:1; 
  u_int16_t rst:1; 
  u_int16_t psh:1; 
  u_int16_t ack:1; 
  u_int16_t urg:1; 
  u_int16_t res2:2; 
  #elif __BYTE_ORDER == __BIG_ENDIAN 
  u_int16_t doff:4; 
  u_int16_t res1:4; 
  u_int16_t res2:2; 
  u_int16_t urg:1; 
  u_int16_t ack:1; 
  u_int16_t psh:1; 
  u_int16_t rst:1; 
  u_int16_t syn:1; 
  u_int16_t fin:1; 
  #endif 
  u_int16_t window; 
  u_int16_t check; 
  u_int16_t urg_prt; 
  }; 
  
  source发送TCP数据的源端口 
  dest接受TCP数据的目的端口 
  
  seq标识该TCP所包含的数据字节的开始序列号 
  
  ack_seq确认序列号,表示接受方下一次接受的数据序列号. 
  
  doff数据首部长度.和IP协议一样,以4字节为单位.一般的时候为5 
  
  urg如果设置紧急数据指针,则该位为1 
  
  ack如果确认号正确,那么为1 
  
  psh如果设置为1,那么接收方收到数据后,立即交给上一层程序 
  
  rst为1的时候,表示请求重新连接 
  
  syn为1的时候,表示请求建立连接 
  
  fin为1的时候,表示亲戚关闭连接 
  
  window窗口,告诉接收者可以接收的大小 
  
  check对TCP数据进行较核 
  
  urg_ptr如果urg=1,那么指出紧急数据对于历史数据开始的序列号的偏移值 
  
  关于TCP协议的详细情况,请查看 RFC793 
  
  7.6 TCP连接的建立 
  TCP协议是一种可靠的连接,为了保证连接的可靠性,TCP的连接要分为几个步骤.我们把这个连接过程称为"三次握手". 
  
  下面我们从一个实例来分析建立连接的过程. 
  
  第一步客户机向服务器发送一个TCP数据包,表示请求建立连接. 为此,客户端将数据包的SYN位设置为1,并且设置序列号seq=1000(我们假设为1000). 
  
  第二步服务器收到了数据包,并从SYN位为1知道这是一个建立请求的连接.于是服务器也向客户端发送一个TCP数据包.因为是响应客户机的请求,于是服务器设置ACK为1,sak_seq=1001(1000+1)同时设置自己的序列号.seq=2000(我们假设为2000). 
  
  第三步客户机收到了服务器的TCP,并从ACK为1和ack_seq=1001知道是从服务器来的确认信息.于是客户机也向服务器发送确认信息.客户机设置ACK=1,和ack_seq
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值