- title: 网络基础学习总结(1)
- tags: 网络
- categories:笔记
- date: 2017-06-18 17:40:54
做web开发呢,除了前端后端技术要熟练使用外,想要更进一步学习web原理,那必须还得了解计算机网络的一些基础知识。计算机网络范围其实很广,内容杂多。说来惭愧啊,上学时候,上课都没有认真思考,实验也没有充分发挥主观能动性,浪费了现有硬件资源来对网络进行更深的学习。但是,在日常工作中,对这些原理的东西也不能一概不知。就打算来说说,网络中的一些基础内容,包括:数据传输模型OSI,TCP/IP,TCP协议的建立与释放,IP数据报的传输与数据格式等等。
网络通信模型
因为从计算机整个发展到现在的历程来看,从没有操作系统的单太计算机,只是用于数据简单处理的计算机,到后来的批处理系统,多道程序系统,到分时系统,实时系统的发展,计算机处理能力呈现爆炸性增长,伴随着处理能力提升,早起不同的计算机公司开发自己定义的计算机系统以及计算机通信协议,导致了不同的公司或者说不同的硬件底层支持的计算机的通信会很复杂,硬件的异构型造成了计算机通信的成本花费很大。特别是万维网的创建,更是将整个实验室,县城,市区到国家之间的计算机通信互联的现实需求推至顶端。
那么为了不同公司,不同类型的计算机进行通信更高效,方便,那么无规矩不成方圆。权威机构当然就联合起来,共同定制合理有效的计算机通信模型以及协议等等。也是适应时代发展的需要和推动计算机互联网的快速发展的必然结果。
OSI参考模型
该模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架。开放系统互联参考模型的系统结构共分7层。在该模型中层与层之间进行对等通信,且这种通信只是逻辑上的,真正的通信都是在最底层-物理层实现的,每一层要完成相应的功能,下一层为上一层提供服务,从而把复杂的通信过程分成了多个独立的、比较容易解决的子问题。--引用自百度OSI
下面这张图,把整个OSI协议模型以及每层协议栈上的一些协议给列出来了:(图片来源自网络)
该OSI通信框架知道有7层,那七层,每层大致做得什么,有什么作用就够了。在此就不细说了。
TCP/IP参考模型
TCP/IP参考模型是计算机网络的祖父ARPANET和其后继的因特网使用的参考模型。ARPANET是由美国国防部DoD(U.S.Department of Defense)赞助的研究网络。逐渐地它通过租用的电话线连结了数百所大学和政府部门。当无线网络和卫星出现以后,现有的协议在和它们相连的时候出现了问题,所以需要一种新的参考体系结构。这个体系结构在它的两个主要协议出现以后,被称为TCP/IP参考模型(TCP/IP reference model)。 --百度
这个TCP/IP参考模型有四层:网络访问层、网际互联层、传输层(主机到主机)、和应用层。(图片引用自网络)
两种模型的比较
共同点
(1)OSI参考模型和TCP/IP参考模型都采用了层次结构的概念。
(2)都能够提供面向连接和无连接两种通信服务机制。
不同点
(1)OSI采用的七层模型,而TCP/IP是四层结构。
(2)TCP/IP参考模型的网络接口层实际上并没有真正的定义,只是一些概念性的描述。而OSI参考模型不仅分了两层,而且每一层的功能都很详尽,甚至在数据链路层又分出一个介质访问子层,专门解决局域网的共享介质问题。
(3)OSI模型是在协议开发前设计的,具有通用性。TCP/IP是先有协议集然后建立模型,不适用于非TCP/IP网络。
(4)OSI参考模型与TCP/IP参考模型的传输层功能基本相似,都是负责为用户提供真正的端对端的通信服务,也对高层屏蔽了底层网络的实现细节。所不同的是TCP/IP参考模型的传输层是建立在网络互联层基础之上的,而网络互联层只提供无连接的网络服务,所以面向连接的功能完全在TCP协议中实现,当然TCP/IP的传输层还提供无连接的服务,如UDP;相反OSI参考模型的传输层是建立在网络层基础之上的,网络层既提供面向连接的服务,又提供无连接的服务,但传输层只提供面向连接的服务。
(5)OSI参考模型的抽象能力高,适合与描述各种网络;而TCP/IP是先有了协议,才制定TCP/IP模型的。
(6)OSI参考模型的概念划分清晰,但过于复杂;而TCP/IP参考模型在服务、接口和协议的 区别上不清楚,功能描述和实现细节混在一起。
(7)TCP/IP参考模型的网络接口层并不是真正的一层;OSI参考模型的缺点是层次过多,划分意义不大但增加了复杂性。
(8)OSI参考模型虽然被看好,由于没把握好时机,技术不成熟,实现困难;相反,TCP/IP参考模型虽然有许多不尽人意的地方,但还是比较成功的。
-- 引用自百度
数据通信
在了解了现代计算机之间的数据通信模型后,就可以来具体看看计算机之间是如何进行数据传递的,在传递过程中会遇到什么问题,数据是以什么样的形式进行封装传输的。若是在传输中出现错误,又是如何进行处理的。其实,有很多问题值得我们思考并进行更深层次的理解与代码开发。
因为数据的传输大致就是两种:WLAN广域网内的计算机互联通信以及LAN局域网内的主机进行互联通信。所以其实数据的产生和传输都是需要硬件支持的,若是能了解一些常见的计算机网络硬件如:网络交换机,路由器,集线器等,还有以太网技术和VLAN虚拟局域网,可能会更能加深对整个数据通信过程的理解把。有些硬件中对协议通信的支持能力很高,智能的接收数据,转发数据等等,有些则是常规的数据转发推送等。
数据封装解封流程
因为,从上面模型可以知道。数据的传输过程中,需要经过不同层次的协议栈,那么每个层次对传输的数据是如何处理的呢?[以以太网网络为背景]
其实,在实际数据的通信传输过程中,在发送端:每层协议栈都会在上层协议的基础上,添加本层的头数据或者尾部添加数据。并且,每层添加的协议头部的数据结构其实也是不一样的,因为不同层次的协议栈有不同的处理作用,就造成了有不同的需求,所以协议头当然是不同的。直到封装数据到最后成以太网帧(在以太网中),在硬件设备和网络中进行数据传送。
在接收端:因为发送端在发送数据会进行协议层封装,那么接收端就是解封装。根据每次协议层的规则,拆分协议头数据进行记录和处理。直到最后将发送端的应用程序,发送有效数据传输到接收端的具体应用中,进行数据处理。
因为不同层次的协议会对数据处理处理,所以,每个对每个层次的数据的称呼也就不一样了:
物理层: 比特(bit)
链路层: 帧(Frame)
网络层: 分组数据包(Packet)
传输层: 数据段(Segment)
上述两端的数据通信流程可以通过图示更加形象的表现处理:
【TCP/IP参考模型】
可以看到,从最顶层的应用程的用户数据的产生,传输到下层TCP,会对数据进行TCP首部封装成段数据(segment),在往下层网络层传输,该层会添加IP首部,这时候数据就变成了分组数据包,再往下就是主机到以太网的连接层,封装成以太网帧(frame),添加以太网首部,尾部等等。最后就可以将整个数据发送到网络中。
在大致了解了网络总计算机的数据通信要经过基层协议栈的处理封装,到最后数据传输,再到数据解封到接收端的过程后,就可以对每层的协议进行了解了,看看,每个层次的协议数据结构是怎样的,每层协议的封装的协议头部有什么用,以及每个层次协议栈中有哪些常见的协议,都可以进行了解和学习。
TCP协议栈
在传输层中,主要的协议就是TCP以及UDP协议,前者是面向连接的字节流可靠的数据通信协议;后者是无连接的不可靠的协议。其实,这两种协议在实际应用中都很广泛,并且内部内容还不少。这里因为是基础知识内容学习,就打算只是讲讲tcp协议内容。
什么是TCP(Transmission Control Protocol),可以查看百度TCP。通过名字知道它是传输控制协议。就是在主机通信过程中,在传输层对数据进行控制处理的协议。这个面向连接的可靠服务的协议,功能还不少,包括数据正确性校验,超时重传,窗口流量控制等等。这些功能都是为了支持可靠性而服务的。
TCP数据段数据格式
【1】那么,在传输层中,tcp段数据的内部格式是怎么样的?如下图:
可以看到,tcp数据在ip数据包中的位置,以及整个tcp段数据的数据格式。
【2】根据上图的数据段的数据格式,每个位置的字段内容代表什么?
- 源端口和目的端口号: 这两个字段均为16位长度,表示发送端和接收端的端口,用于确认发送端和接收端的应用程序。发送端的IP地址和端口号以及接收端的IP地址和端口号可以确认一个在internet上的TCP连接(端对端的连接建立)。(PORT + IP : 定位主机与主机上的应用程序)
- 序列号: 序列号是一个32位长度字段,表示分配给TCP包的编号。序列号用来标识应用程序从TCP的发送端到接收端发送的字节流。当TCP开始连接的时候,发送一个序列号给接收端,连接成功后,这个序列号作为初始序列号ISN。之后连接成功发送的第一个字节的序列号位ISN+1,之后发送数据ISN将按照字节的大小进行递增,当序列号大于2的32次方-后,从0开始。
- 确认号: 发送方对发送的首字节进行了编号,当接收方成功接收后,发送接收成功的序列号加1标识确认回发送端,发送方再次发送的时候就从这个返回的确认号开始。(三次握手)
- 头部长度: 表示TCP头部的长度,由于TCP的数据有可选字段,头部长度用于表示头部的长度。该项长度位4位,单位是32位字长的数据。TCP的头部最长为60字节,如果没有可选字段通常是20个字节。
- 保留位: 6位长度没有使用,必须设置为0.
- ** 控制位**: 6位长度的控制位,可以多个位一起设置。含义如下表:
字段 含义
URG 紧急指针字段
ACK 表示确认号有效
PSH 表示接收方需要尽快将此数据交给应用层
RST 重建连接
SYN 用于发起一个TCP连接
FIN 用于表示将要断开TCP的连接
- 窗口尺寸: 窗口的尺寸也称作接收窗口大小,<u>表示本机上TCP协议可以接收的以字节位单位的数目</u>,本字段为16位长度。
- TCP校验和: 16位长度,用于校验TCP传输数据的正误,包括TCP头和所有数据,TCP的数据必须强制校验。
- 紧急指针: 16位长度,只有设置了URG位为1这个字段数据才会有效,他指出了紧急接收数据的字节的顺序编号。
- 选项: 经常使用的为最大分段长度MSS。tcp连接通常在第一个通信的报文中指明这个选项,它指明当前主机所能接收的最大报文长度。
【3】TCP在linux中代码定义:
为了校验或者说从程序员的角度来理解这个TCP协议,最直接的方式就是通过底层代码的方式来看了。那么,在linux系统中,对tcp的定义确实可以看到。
可以查看cat /usr/include/linux/tcp.h
可以看到具体的对tcp的数据格式的定义:
#ifndef _LINUX_TCP_H
#define _LINUX_TCP_H
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/socket.h>
struct tcphdr {
__be16 source; /*源地址端口*/
__be16 dest; /*目的地址端口*/
__be32 seq; /*序列号*/
__be32 ack_seq; /*确认序列号*/
#if defined(__LITTLE_ENDIAN_BITFIELD) /*小端对齐*/
__u16 res1:4, /*保留*/
doff:4, /*偏移(头部长度)*/
fin:1, /*关闭连接标志*/
syn:1, /*请求tcp连接标志*/
rst:1, /*重置连接标志*/
psh:1, /*接收方尽快将数据推送至应用层*/
ack:1, /*确认序列号标志*/
urg:1, /*紧急指针标志*/
ece:1, /*拥塞标志位*/
cwr:1; /*拥塞标志位*/
#elif defined(__BIG_ENDIAN_BITFIELD) /*大端对齐*/
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__be16 window; /*滑动窗口大小*/
__sum16 check; /*校验和*/
__be16 urg_ptr; /*紧急字段指针*/
};
/*
* The union cast uses a gcc extension to avoid aliasing problems
* (union is compatible to any of its members)
* This means this part of the code is -fstrict-aliasing safe now.
*/
union tcp_word_hdr {
struct tcphdr hdr;
__be32 words[5];
};
根据上面的tcp端数据的数据格式和上述代码定义结合起来理解,可以发现代码就是按照tcp的数据段的数据格式内容来进行定义的,只不过是区分了内存存储字节的大端对齐还是小端对齐的方式而已。
TCP连接与释放
在理解了传输层协议栈中tcp协议数据段的内部数据格式,以及格式中每个字段代表的内容。接下来就可以来看看一个tcp连接是如何连接和释放的。没错,就是大名鼎鼎的TCP三次握手和四次挥手。
【1】TCP三次握手
在广域网或者局域网内,两台主机要进行tcp的连接,数据交互,都必须遵循TCP/IP协议模型中tcp连接规则:TCP三次握手。
即tcp是面向字节流的连接,在确认两个主机可以进行tcp交互的前提是,tcp链路连接必须要在数据交互前建立起来。
TCP三次握手,其实就是TCP连接建立的过程,三次握手的目的是同步连接双方的序列号和确认号并交换TCP窗口大小信息。
因为两台主机要进行tcp数据交互,对于每单独的主机,你得知道双发对于数据包发送的规则,即从那个包开始发送,有什么标志说明某个数据是第一次发送的数据,什么时候你发送过来的数据是结束数据?每次你那边能接收到多少字节的数据?所以,三次握手就是为了数据交互做探测准备的。
下面来分别说说这个TCP三次握手的细节流程:【主要的就是同步序列号和确认号】
客户端主机A主动打开,发送连接请求报文段(segment),将tcp连接标志为SYN值为1,表示要发起一个连接;将seq(序列号:分配给报文段的编号标志)设置为x(TCP规定SYN=1时不能携带数据,x为随机产生的一个值),然后客户端状态进入SYN_SEND。
服务器端B收到A发送过来的报文,进行确认处理,表示收到的序列号有效,设置ACK=1;因为也要发送一个请求连接进行返回,所以SYN=1;因为服务器端B也要发送报文段数据,所以设置报文序列号为seq=y(这个服务器端B主机的报文段序列号,也是为了客户机A接收到,加1处理设置确认序列号返回用的),这时候,最重要的是设置确认序列号ack,因为在第一步中接收到了主机A发送的序列号x,这时候,接收端需要在接收到的序列号基础上加1,将值x+1作为确认序列号设置到tcp报文段中,所以设置ack=x+1。
表示:我已经收到发来的序列号了,确认序列号为x+1,你下次发送报文段数据的序列号就从x+1开始设置,这样,我才认可是你发送的数据,才是有效数据。。客户端主机A接收服务器端的反馈数据,进行再次确认,若是得到的ack为第一次发送的序列号基础上加1,那么说明这个报文段是有效的,设置ACK=1;因为不是要求重新发送tcp请求,所以,不用在设置SYN=1了。只是需要校验确认序列号,这边确认成功,还要对接收到的服务器端序列号y进行设置,在y基础上加1,将y+1作为确认序列号设置到报文段的ack字段中,为了让服务器端进行报文校验,即设置ack=y+1(当B端接收到报文段后,获取ack=y+1,说明与上次发送的报文序列号差1,报文段有效),因为确认报文有效了,所以,此时可以将这个发送的报文段的序列号设置为接收来的确认序列号seq=x+1,说明,正式的数据发送已经开始了,从x+1开始的序列号的报文段就是我发送的。
seq序列号表示发送的报文段的报文编号,ack序列号表示对方接收端处理后的确认序列号,用于校验报文段是否正确的。
在三次握手建立好连接之后,就可以进行正常的数据交互了,当然了,每次数据交互发送的报文段都是又这些例如序列号seq,接收方的确认序列号,控制表示,源和目的端口号等等。
为什么客户端要进行二次确认?
因为会出现已失效的连接请求报文情况:
正常来说,客户端发出连接请求,但因为连接请求报文丢失而未收到确认。于是客户端再次发出一次连接请求,后来收到了确认,建立了连接。数据传输完毕后,释放了连接,客户端一共发送了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,没有"已失效的连接请求报文段"。
现在假定一种异常情况,即客户端发出的第一个连接请求报文段并没有丢失,只是在某些网络节点长时间滞留了,以至于延误到连接释放以后的某个时间点才到达服务端。本来这个连接请求已经失效了,但是服务端收到此失效的连接请求报文段后,就误认为这是客户端又发出了一次新的连接请求。于是服务端又向客户端发出请求报文段,同意建立连接。假定不采用三次握手,那么只要服务端发出确认,连接就建立了。
由于现在客户端并没有发出连接建立的请求,因此不会理会服务端的确认,也不会向服务端发送数据,但是服务端却以为新的传输连接已经建立了,并一直等待客户端发来数据,这样服务端的许多资源就这样白白浪费了。
采用三次握手的办法可以防止上述现象的发生。比如在上述的场景下,客户端不向服务端的发出确认请求,服务端由于收不到确认,就知道客户端并没有要求建立连接。
【2】TCP四次挥手
当两段AB的tcp连接传输完成之后,要进行断开,就像tcp连接要进行三次握手才能正确的传递数据;在tcp的断开也要进行一些规则的流程:<font color="red">TCP四次挥手</font>。
再来看看tcp四次挥手的流程图:
挥手流程分析:
客户端A主机在得到或者处理完成数据需求之后,就准备关闭连接了,先会发送一个报文给服务器端B主机(没有数据),设置报文控制位FIN=1
,要求断开连接。该报文序列号seq设置位u,seq=u,客户端在将该报文发送出去后,就进入FIN_WAIT_1状态。服务器端B主机收到了来自客户端的请求后,校验确认序列号后设置ACK=1,同时也设置响应报文序列号seq=v,并将接收到的客户端的报文的序列号+1作为确认序列号,即设置ack=u+1,放回给客户端主机A,此时服务器端进入了CLOSE_WAIT状态。(因为步骤一中客户端A的断开请求又多种情况,主动权也是在客户端主机A,那么就会又这种状况,服务器主机B的应用处理还没又完成,就收到客户端的断开请求,这时候在响应客户端说,服务器收到了断开请求,准备断开后,进入close_wait状态后,就要通知服务器端的处理程序,要进行断开了,至于怎么处理就要看程序的控制了。响应请求未发送FIN控制位值)
当通知完服务器端的应用程序,要进行关闭后,服务器端就会被动关闭,就会发送一个断开请求,FIN=1,并根据上次发送响应报文的确认序列号u+1,又设置同样的值,这样,就说明这此FIN断开请求与上次响应请求是一致的,并同时设置确认序列号有效ACK=1,设置该次请求报文序列号seq=w。这个时候,服务器端进入LAST_ACK状态,即最后一次发送确认序列号。(这次请求是服务器端关闭应用程序后,在被动关闭的状态下发送的断开连接请求。)
客户端第二次接收到服务器端信息(但是是第一次接收服务器端FIN断开连接请求),即从报文段中知道FIN=1,即服务器请求断开连接了,客户端就会进入TIME_WAIT状态,接着发送一个确认报文,校验收到的服务器端的FIN断开请求,设置ACK=1,报文序列号设置为客户端的第二次发送,即在第一次发送的seq=u的基础上再加1,即seq=u+1,同时ack将会设置为从服务器端B主机接收的报文序列号w的基础上加1,ack=w+1,表明接收到了断开请求且确认序列号有效。最后,服务器端和客户端都会进入CLOSE_WAIT状态。
为什么握手只要三次,挥手却要四次?
因为服务端在LISTEN状态下,收到建立请求的SYN报文后,<u>把ACK和SYN放在一个报文里发送给客户端</u>。而连接关闭时,当收到对方的FIN报文时,仅仅表示对方没有需要发送的数据了,但是还能接收数据,己方未必数据已经全部发送给对方了,所以己方可以立即关闭,也可以将应该发送的数据全部发送完毕后再发送FIN报文给客户端来表示同意现在关闭连接。【LAST_ACK表示没有数据要发送了】
从这个角度而言,再断开连接的时候,<u><font color="red">服务端的ACK和FIN一般都会分开发送</font></u>。
IP协议栈
在TCP/IP参考模型中的网际层中的IP协议栈,在数据传输过程中,会对上层的tcp处理后的数据段(segment),在此进行封装,加上自己的ip头部数据。
其中,虽然arp,icmp协议并不是该层的协议,但是两者在该层中是与ip协议进行协同工作的。即IP层中包含网际控制报文协议和地址识别协议。
前者ICMP用于报告网络上的某些出错情况,允许网际路由器传输出现差错信息或者测试报文。
后者ARP处于IP层和数据链路层之间,它是用来将32位ip地址与MAC地址转换用的。
关于ip更详细的介绍,参考百度-ip
IP数据包数据格式
好了,在简要介绍了网际层的常见协议和作用外,就可以看看该层的数据包中的数据格式和内部字段代表的含义。
【1】数据包数据格式
可以看到,相比较TCP的数据段内的数据格式,ip内部的数据也不少。
【2】字段含义
根据上面一步中的IP数据包内部数据格式,下面可以来分别看看内部的字段分别代表了什么意思。
- 版本号:ip协议的版本号,长度4位,规定网络实现的IP版本。IPV4该值为4。
- 首部长度: 首部长度指的是IP字段除去数据的整个头部数据长度,是以32位的字作为计算单位。最短的IP头部长度是20字节,最长为60个字节。所以该属性值的可取值范围是5 - 15。
- 服务类型(TOS): ip服务类型字段长度8位。包括3位优先权,4位T服务类型子字段和1位保留字段:
字段 优先权 D T R F 保留
长度 3位 1位 1位 1位 1位 1位
含义 优先级 延迟 吞吐量 可靠性 费用 未用
其中:后四位字段只能用一个,若是全部为0表示一般服务。服务类型字段由应用程序进行设置,路由器仅在必要的时候进行读取,不会进行设置。
- 总长度:总长度字段长度16位,表示以字节为单位的数据报文长度,长度包含IP头部和数据部分。 所以ip数据报文总长度可以到达65535个字节长度。
- 标识和片偏移: IP每次发一份数据报文都会填写一个标识用来表示此数据包,发送完后此值会加1。所以,在传输数据>mtu=1500个字节的时候,需要对数据报文进行分片。在分片的时候,需要对分片的每一个数据设置序号和ip报文来源,都可以在标识种进行设置。还要加上分片数据在源数据报文种的偏移地址,便于接收端收到所有分片的ip数据报进行重新组合。
-
生存时间: TTL(time to live) 字段的值表示数据报文最多可以经过的路由器的数量。源主机发送数据时候设置TTL(一般为32或者64),没经过一个
路由器进行分转,TTL的值减一。当TTL=0的时候,路由器会丢弃此包,并发送一个ICMP报文通知源主机。目的: 防止在数据报传输过程种出现错误,引起包在Internet的路由器之间不断循环,因而加入TTL机制限制报文经过的路由总数。 - 协议类型: 该字段为8位长度,即最多可以表示255种协议类型,表示IP上承载的是什么高级协议。目的是为了在网际层种进行封包和解包的过程中,TCP/IP协议栈知道将这些数据包发给那个层的协议栈做相关的处理。协议类型含义如下表:
值 协议类型
1 ICMP
2 TCP
6 IMGP
17 UDP
...
-
头部检验和: 校验和是一个16位长度数值。使用循环冗余校验生成,其作用是保证IP帧的完整性。发送端发送数据的时候要计算CRC16校验值,填写到此
字段中;接收端会计算IP的校验值并与该字段进行匹配,如果不匹配表示帧发生错误,将丢弃此报文。因为CRC16的计算与TTL有关,所以每次经过路由器都要重新计算。 - 源地址和目的地址: 即为发送端和接收端主机的ip地址。
【3】ip数据包在linux中代码定义:
若是像查看ip数据包在linux中代码的定义情况,则可以通过命令cat /usr/include/linux/ip.h
查看:
/*IP头部数据结构的定义*/
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD) /*小端对齐*/
__u8 ihl:4, /*ip头部长度,单位是32bit*/
version:4; /*IP版本,值为4 IPV4*/
#elif defined (__BIG_ENDIAN_BITFIELD) /*大端*/
__u8 version:4, /*版本 ipv4*/
ihl:4; /*IP头部长度*/
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos; /*服务类型*/
__be16 tot_len; /*总长度*/
__be16 id; /*数据报标识*/
__be16 frag_off; /*分片数据片偏移量*/
__u8 ttl; /*生存时间*/
__u8 protocol; /*协议类型:tcp,udp,icmp,imgp*/
__sum16 check; /*头部校验和*/
__be32 saddr; /*源主机ip地址*/
__be32 daddr; /*目的主机ip地址*/
/*The options start here. */ /*ip选项*/
};
可以根据代码中,定义的变量与ip数据包数据格式中字段进行对比就可以知道,代码的编写中变量的定义就是参考ip数据包格式来的。
以太网
在发送端,数据通过应用层到传输层,网际IP层,最后越是贴近物理层,封装成以太网帧(以太网中)进行传输。再来看看这个帧内部信息。
以太网帧数据格式
【1】以太网帧数据格式如下图:
可以看到,以太网帧的数据格式挺简单的。包括以太网头部中的:目的mac,源mac,类型。mac代表当前主机和通信主机的硬件地址。类型,则是用于表明当前帧是什么类型的数据帧,是ip数据包,还是arp请求等等。后面还有个以太网尾部CRC,4个字节用来做循环冗余校验的。
其中,通过以太网帧中的数据长度46~1500,就涉及到一个概念MTU,也就是最大传输单元,表明单个帧数据最多能传输1500个字节数据(不包括头部数据)。
【2】帧在linux代码中的定义:
若是想查看linux中,是如何对以太网帧进行代码定义的话,可以通过命令cat /usr/include/linux/if_ether.h
来查看,可以看到帧的全部字段和类型数据:
#ifndef _LINUX_IF_ETHER_H
#define _LINUX_IF_ETHER_H
#include <linux/types.h>
/*
* IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
* and FCS/CRC (frame check sequence).
*/
#define ETH_ALEN 6 /* Octets in one ethernet addr 以太网地址:mac地址 */
#define ETH_HLEN 14 /* Total octets in header. 以太网头部的总长度:源地址+目的地址+数据类型 */
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS 不含CRC校验的数据最小长度:46+12+2 */
#define ETH_DATA_LEN 1500 /* Max. octets in payload 帧内数据的最大长度MTU*/
#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS 不含CRC校验和的最大以太网数据长度*/
#define ETH_FCS_LEN 4 /* Octets in the FCS CRC校验和字段长度*/
/*
* These are the defined Ethernet Protocol ID's.
下面定义的是以太网头部中类型字段选址:代表不同的数据类型 2个字节 2^16种类型
*/
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */
#define ETH_P_IP 0x0800 /* Internet Protocol packet 表示IP数据报文 */
#define ETH_P_X25 0x0805 /* CCITT X.25 */
#define ETH_P_ARP 0x0806 /* Address Resolution packet ARP协议数据类型*/
#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */
#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */
#define ETH_P_BATMAN 0x4305 /* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_DEC 0x6000 /* DEC Assigned proto */
#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */
#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */
#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */
#define ETH_P_LAT 0x6004 /* DEC LAT */
#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */
#define ETH_P_CUST 0x6006 /* DEC Customer use */
#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */
#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */
#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
#define ETH_P_ATALK 0x809B /* Appletalk DDP */
#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
#define ETH_P_IPX 0x8137 /* IPX over DIX */
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */
#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */
#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol
* defined in draft-wilson-wrec-wccp-v2-00.txt */
#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */
#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */
#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */
#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */
#define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */
#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport
* over Ethernet
*/
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */
#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */
#define ETH_P_TIPC 0x88CA /* TIPC */
#define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */
#define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */
#define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */
#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */
#define ETH_P_NCSI 0x88F8 /* NCSI protocol */
#define ETH_P_PRP 0x88FB /* IEC 62439-3 PRP/HSRv0 */
#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
#define ETH_P_TDLS 0x890D /* TDLS */
#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
#define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */
#define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */
#define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */
#define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value
* then the frame is Ethernet II. Else it is 802.3 */
/*
* Non DIX types. Won't clash for 1500 types.【MTU】
*/
#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
#define ETH_P_802_2 0x0004 /* 802.2 frames */
#define ETH_P_SNAP 0x0005 /* Internal only */
#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */
#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/
#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */
#define ETH_P_CAN 0x000C /* CAN: Controller Area Network */
#define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/
#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */
#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
#define ETH_P_CONTROL 0x0016 /* Card specific control frames */
#define ETH_P_IRDA 0x0017 /* Linux-IrDA */
#define ETH_P_ECONET 0x0018 /* Acorn Econet */
#define ETH_P_HDLC 0x0019 /* HDLC frames */
#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */
#define ETH_P_DSA 0x001B /* Distributed Switch Arch. */
#define ETH_P_TRAILER 0x001C /* Trailer switch tagging */
#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */
#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */
#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */
#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */
/*
* This is an Ethernet frame header.
*/
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr 以太网目的Mac地址 */
unsigned char h_source[ETH_ALEN]; /* source ether addr 以太网源MAC地址*/
__be16 h_proto; /* packet type ID field 以太网包类型:16位*/
} __attribute__((packed));
#endif /* _LINUX_IF_ETHER_H */
硬件设备
不同层次对应的硬件配置:(通常情况下,不包括三层交换机,四层交换机..)
物理层:网卡,网线,集线器,中继器,调制解调器
数据链路层:网桥,交换机
网络层:路由器
网关工作在第四层传输层及其以上
集线器是物理层设备,采用广播的形式来传输信息。
交换机就是用来进行报文交换的机器。多为链路层设备(二层交换机),能够进行地址学习,采用存储转发的形式来交换报文.。
路由器的一个作用是连通不同的网络,另一个作用是选择信息传送的线路。选择通畅快捷的近路,能大大提高通信速度,减轻网络系统通信负荷,节约网络系统资源,提高网络系统畅通率。
交换机和路由器的区别?
交换机拥有一条很高带宽的背部总线和内部交换矩阵。交换机的所有的端口都挂接在这条总线上,控制电路收到数据包以后,处理端口会查找内存中的地址对照表以确定目的MAC(网卡的硬件地址)的NIC(网卡)挂接在哪个端口上,通过内部交换矩阵迅速将数据包传送到目的端口,目的MAC若不存在则广播到所有的端口,接收端口回应后交换机会“学习”新的地址,并把它添加入内部MAC地址表中。
使用交换机也可以把网络“分段”,通过对照MAC地址表,交换机只允许必要的网络流量通过交换机。通过交换机的过滤和转发,可以有效的隔离广播风暴,减少误包和错包的出现,避免共享冲突。
交换机在同一时刻可进行多个端口对之间的数据传输。每一端口都可视为独立的网段,连接在其上的网络设备独自享有全部的带宽,无须同其他设备竞争使用。当节点A向节点D发送数据时,节点B可同时向节点C发送数据,而且这两个传输都享有网络的全部带宽,都有着自己的虚拟连接。假使这里使用的是10Mbps的以太网交换机,那么该交换机这时的总流通量就等于2×10Mbps=20Mbps,而使用10Mbps的共享式HUB时,一个HUB的总流通量也不会超出10Mbps。
总之,交换机是一种基于MAC地址识别,能完成封装转发数据包功能的网络设备。交换机可以“学习”MAC地址,并把其存放在内部地址表中,通过在数据帧的始发者和目标接收者之间建立临时的交换路径,使数据帧直接由源地址到达目的地址。
从过滤网络流量的角度来看,路由器的作用与交换机和网桥非常相似。但是与工作在网络物理层,从物理上划分网段的交换机不同,路由器使用专门的软件协议从逻辑上对整个网络进行划分。例如,一台支持IP协议的路由器可以把网络划分成多个子网段,只有指向特殊IP地址的网络流量才可以通过路由器。对于每一个接收到的数据包,路由器都会重新计算其校验值,并写入新的物理地址。因此,使用路由器转发和过滤数据的速度往往要比只查看数据包物理地址的交换机慢。但是,对于那些结构复杂的网络,使用路由器可以提高网络的整体效率。路由器的另外一个明显优势就是可以自动过滤网络广播。
**集线器与路由器在功能上有什么不同? **
首先说HUB,也就是集线器。它的作用可以简单的理解为将一些机器连接起来组成一个局域网。而交换机(又名交换式集线器)作用与集线器大体相同。但是两者在性能上有区别:集线器采用的式共享带宽的工作方式,而交换机是独享带宽。这样在机器很多或数据量很大时,两者将会有比较明显的。而路由器与以上两者有明显区别,它的作用在于连接不同的网段并且找到网络中数据传输最合适的路径。路由器是产生于交换机之后,就像交换机产生于集线器之后,所以路由器与交换机也有一定联系,不是完全独立的两种设备。路由器主要克服了交换机不能路由转发数据包的不足。
总的来说,路由器与交换机的主要区别体现在以下几个方面:
(1)工作层次不同
最初的的交换机是工作在数据链路层,而路由器一开始就设计工作在网络层。由于交换机工作在数据链路层,所以它的工作原理比较简单,而路由器工作在网络层,可以得到更多的协议信息,路由器可以做出更加智能的转发决策。
(2)数据转发所依据的对象不同
交换机是利用物理地址或者说MAC地址来确定转发数据的目的地址。而路由器则是利用IP地址来确定数据转发的地址。IP地址是在软件中实现的,描述的是设备所在的网络。MAC地址通常是硬件自带的,由网卡生产商来分配的,而且已经固化到了网卡中去,一般来说是不可更改的。而IP地址则通常由网络管理员或系统自动分配。
(3)传统的交换机只能分割冲突域,不能分割广播域;而路由器可以分割广播域
由交换机连接的网段仍属于同一个广播域,广播数据包会在交换机连接的所有网段上传播,在某些情况下会导致通信拥挤和安全漏洞。连接到路由器上的网段会被分配成不同的广播域,广播数据不会穿过路由器。虽然第三层以上交换机具有VLAN功能,也可以分割广播域,但是各子广播域之间是不能通信交流的,它们之间的交流仍然需要路由器。
(4)路由器提供了防火墙的服务
路由器仅仅转发特定地址的数据包,不传送不支持路由协议的数据包传送和未知目标网络数据包的传送,从而可以防止广播风暴。
该部分截取自:OSI七层模型详解
总结
上面的内容仅仅是网络的很小很小的基础知识部分,也是自己学习过程中一些总结。包括数据通信的OSI/TCP参考模型,并对数据通信中每层的协议栈进行分析和内部数据结构的图解,同时也将linux系统对每层协议的代码定义也罗列出来,帮助程序员加深理解。其实,内部还有很多东西值得去学习,分析,思考。这篇就到这....
[图片上传失败...(image-84c371-1511017700608)]
参考:
Liux网络编程(第二版)
TCP:三次握手、四次握手、backlog及其他