文章目录
前两天中兴电话面试竟然问了网络模型分层这个不疼不痒的题目,尴尬的是还记得tcp/ip模型是4层,但当时怎么数都是5层(被谢希仁的5层模型洗脑了),看来还是得复习复习
tcp首部封装了端口号,ip首部封装了IP地址,以太网首部封装了主机的物理mac地址。
以太网帧(Frame)格式
其中的源地址和目的地址是指网卡的硬件地址(也叫MAC地址),长度是48位,是在网卡出厂时固化的。用ifconfig命令看一下,“HWaddr00:15:F2:14:9E:3F”部分就是硬件地址。协议字段有三种值,分别对应IP、ARP、RARP。帧末尾是CRC校验码。
以太网帧中的数据长度规定最小46字节,最大1500字节,ARP和RARP数据包的长度不够46字节,要在后面补填充位(padding)。最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU,如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation)。ifconfig命令的输出中也有“MTU:1500”。注意,MTU这个概念指数据帧中有效载荷的最大长度,不包括帧首部的长度。
ARP协议:用来识别主机ip地址和mac地址的映射
例子:现在,1希望向4发送hello。arp先工作,构造以太网帧(arp数据报)。
目的mac不知道,用6个FF(6个字节)填充,6字节。
填充源mac,6字节。
类型为0806,2字节。
然后是空位8字节。
然后是6字节源mac,4字节源ip,6字节目的mac,4字节目的ip。
构造好之后发送。
现在交换机上相连的主机都得到了这个以太网帧。
只有目的mac是自己主机的mac,或者是6个FF时,这些主机才会接收;否则直接丢弃。
如果目的mac是6个FF,接受之后这些主机会查看目的ip,只有主机4的目的ip能对应上,它需要回应主机1一个包,把源mac设置为自己的mac,而且主机1的mac已经获得了,所以这个回应的以太网帧只有主机1接收。
综上,arp协议就是通过ip地址来获得mac地址。
之后arp就不再用了,两个主机之间靠mac地址通信。
网络层数据包(Packet,也叫分组)格式
ip协议
ip在网络层,解决的主要问题还是数据要送到哪个主机上。
ipv4地址占4个字节。
下面看ip分组:
- ip首部占20个字节:
- 4位版本,描述是ipv4还是ipv6
- 4位首部长度,首部默认是20个字节,如果有选项,首部会变长(还是4字节的倍数)
- 8位服务类型,用来获得更好的服务.这个字段在旧标准中叫做服务类型,但实际上一直没有被使用过.1998年IETF把这个字段改名为区分服务 DS(Differentiated Services).只有在使用区分服务时,这个字段才起作用.
- 16位总长度,总长度指首都及数据之和的长度,单位为字节.因为总长度字段为 16位,所以ip分组的最大长度为 2^16-1=65 535字节。在IP层下面的每一种数据链路层都有自己的帧格式,其中包括帧格式中的数据字段的最大长度,即最大传送单元 MTU (Maximum Transfer Unit)。当一个ip分组封装成链路层的帧时,此ip分组的总长度 (即首部加上数据部分)一定不能超过下面的数据链路层的MTU值,否则要分片。
- 16位标识,IP软件在存储器中维持一个计数器,每产生一个ip分组,计数器就加 1,并将此值赋给标识字段.但这个"标识"并不是序号,因为 IP是无连接的服务,ip分组不存在按序接收的问题.当ip分组由于长度超过网络的 MTU 而必须分片时,这个标识字段的值就被复制到所有的ip分组的标识字段中.相同的标识字段的值使分片后的各ip分组的分片最后能正确地重装成为原来的ip分组.
- 3位标志,但目前只有2位有意义. 标志字段中的最低位记为 MF(More Fragment).MF=1即表示后面"还有分片"的ip分组.MF=0表示这已是若干ip分组的分片中的最后一个.标志字段中间的一位记为DF(Don’t Fragment),意思是"不能分片",只有当 DF=0时才允许分片.
- 13位偏移,较长的分组在分片后,某片在原分组中的相对位置.也就是说,相对用户数据字段的起点,该片从何处开始.片偏移以 8个字节为偏移单位,这就是说,每个分片的长度一定是 8字节(64位)的整数倍.
- 8位生存时间TTL(下一跳),生存时间字段常用的英文缩写是TTL(Time To Live),其表明ip分组在网络中的寿命.由发出ip分组的源点设置这个字段.其目的是防止无法交付的ip分组无限制地在因特网中兜圈子,因而白白消耗网络资源.最初的设计是以秒作为 TTL的单位.每经过一个路由器时,就把TTL减去ip分组在路由器消耗掉的一段时间.若ip分组在路由器消耗的时间小于 1 秒,就把TTL值减 1.当 TTL值为 0时,就丢弃这个ip分组.
- 8位协议,协议字段指出此ip分组携带的数据是使用何种协议,以便使目的主机的IP层知道应将数据部分上交给哪个处理过程.
- 16位校验和,这个字段只检验ip分组的首部,但不包括数据部分。这是因为ip分组每经过一个路由器,都要重新计算一下首都检验和 (一些字段,如生存时间,标志,片偏移等都可能发生变化),不检验数据部分可减少计算的工作量.
- 32位源ip地址。
- 32位目的ip地址。
例子:用户向新浪服务器发送hello
ip分组首先到达路由器100.100.100.1,然后有一个选择路径的问题。路由器先拆包,路由器在网络层工作,mac地址没用,直接丢掉,TTL减1,然后看目的ip是谁,然后路由器查路由表选路(不展开讨论),选择A路由器,转发需要以太网协议,所以还得加上源mac地址和目的mac地址,这时的源mac地址就是路由器自己的mac地址,目的mac地址就是路由器A的mac地址;ip这一层不动。
直到送到新浪服务器;TTL为0时还没到达,被最后一个路由器丢弃(不再转发)。
传输层协议格式
UDP数据报(Datagram)格式
可以看到,UDP协议头部8个字节:
- 16位源端口号
- 16位目的端口号
- 16位UDP长度
- 16位UDP校验和
UDP协议非常简单,最重要的就是端口号的概念,端口号最大是 2^16=65536
例子:
TCP数据段(Segment)格式
- 16位源端口号
- 16位目的端口号
- 32位序号
- 32位确认序号
- 4位首部长度,以4字节为单位
- 保留6位
- URG
- ACK
- PSH
- RST
- SYN
- FIN
- 16位窗口大小
- 16位校验和
- 16位紧急指针
nat映射和打洞
nat映射
内网访问外网ip地址时,网关会做一个NAT映射,将内网ip映射成外网ip,同时依靠端口映射将外网的数据传递给内网的主机。
nat打洞
假设小明和小红两个内网ip通过qq进行视频聊天。二者登录qq时,qq客户端向qq服务器发送数据,qq服务器记录二者的公网ip和端口,此时小明和小红如果要视频聊天可以通过第三方服务器(qq服务器)进行中转,但是数据多转了一手就会造成不必要的延时和卡顿。所以希望小明和小红的客户端直接互相访问。此时又有一个情况,如果内网没有向外网进行数据请求时,他们各自的网关会拦截外部的访问数据(防止攻击),所以小明和小红需要先从qq服务器获得彼此的公网ip和端口,然后小明给小红发送一条信息,这条信息虽然被小红丢弃了,但是在这之后小红给小明发送的数据小明都能接收到;同理,小红给小明先发送一条数据,这条数据被丢弃,然后小明给小红的数据小红都能接收到。这个技术叫nat打洞。qq服务器在这个建立连接过程中扮演了一个提供公网ip和端口的角色,所以第三方服务器是必要的。
此外,如果小红和小明的公网ip相同,证明他们在同一内网,就不需要打洞技术了。小明和小红可以告知彼此的内网ip进行数据传输。
socket编程
服务器最小代码实现
TCP IP协议栈都是在内核态实现的,协议栈什么都有,socket就相当于协议栈实例化的一个对象,因为socket指定了以太网协议,ipv4/ipv6,tcp/udp等。
cs模型: