since
1、网络分层
Osi7层--------->
Tcp/ip4层
应用层:负责处理应用程序的逻辑,比如文件传输、名称查询和网络管理等,它在用户空间实现。通过/etc/services文件可以查看所有知名的应用层协议。
传输层:为两台主机上的应用程序提供端到端的通信,与网络层使用的逐跳通信方式不同,传输层只关心通信的起始端和目的端。
网络层:实现数据包的选路和转发。通信的两台主机一般不是直接相连的,而是通过多个中间节点(路由器)连接的。网络层的任务就是选择这些中间节点,以确定两台主机之间的通信路径。网络层对上层协议隐藏了网络拓扑连接的细节。
数据链路层:实现了网卡接口的网络驱动程序,以处理数据在物理媒介上的传输。
注:TCP/IP4层协议中,ARP/RARP协议位于数据链路层
2、协议简介
(1)ARP(地址解析协议)和RARP(逆地址解析协议),它们实现了IP地址和机器物理地址之间的转换。网络层使用IP地址寻址一台机器,而数据链路层使用物理地址寻址一台机器,因此网络层必须先使用ARP协议将目标机器的IP地址转换为其物理地址,才能使用数据链路层提供的服务; RARP协议用于网络上的某些无盘工作站,它们利用网卡上的物理地址来向网络管理者查询自身的IP地址。
ARP工作原理:主机向自己所在的网络广播一个ARP请求,该请求包含目标机器的网络地址。此网络上的其它机器都将收到这个请求,但只有被请求的目标机器会回应一个ARP应答,其中包含自己的物理地址。
以太网ARP请求/应答报文的格式如下图:
硬件类型字段定义物理地址的类型,它的值为1表示MAC地址。
协议类型字段表示要映射的协议地址类型,它的值为0x800,表示IP地址。
硬件地址长度字段和协议地址长度字段,单位是字节。
操作字段指出4种操作类型:ARP请求(值为1),ARP应答(值为2),RARP请求(值为3),RARP应答(值为4)。
最后4个字段指定通信双方的以太网地址和IP地址。发送端填充除目的端以太网地址外的其它3个字段,以构建ARP请求并发送。接收端若发现该请求的目的端IP地址是自己的,就把自己的以太网地址填进去,然后交换两个目的端地址和发送端地址,以构建ARP应答并返回之。
ARP高速缓存的查看和修改:
ARP维护一个高速缓存,其中包含经常访问或最近访问的机器的IP地址到物理地址的映射,这样就避免了重复的ARP请求,提高了发送数据包的速度。linux下可使用arp命令删除和添加ARP缓存。例如:arp -d 192.168.1.109(删除对应的缓存项),arp -s 192.168.1.109 08:00:27:53:10:67(添加对应的缓存项)。
(2)ICMP(因特网控制报文协议)
如上图,8位类型字段用于区分报文类型,它将ICMP报文分为两大类:一类是差错报文,用来回应网络错误(目标不可达或者重定向等);另一类是查询报文,用来查询网络信息(ping应用程序)。有的ICMP报文还使用8位代码字段进一步细分不同的条件。ICMP报文使用16位校验和字段对整个报文进行循环冗余校验(CRC),以检验报文在传输过程中是否损坏。
(3)IP(因特网协议),根据数据包的目的IP地址来决定如何投递它,若数据包不能直接发送给目标主机,那么IP协议就为它寻找一个合适的下一跳路由器,并将数据包交付给该路由器来转发。多次重复这一过程,数据包最终到达目标主机,或者由于发送失败而被丢弃。可见,IP协议用逐跳的方式确定通信路径。
为上层协议提供无状态、无连接、不可靠的服务
无状态:指IP通信双方不同步传输数据的状态信息,因此所有的IP数据报的发送、传输和接收都是相互独立的、没有上下文关系的。
无连接:指IP通信双方不长久地维持对方的任何信息,这样,上层协议每次发送数据的时候,都必须明确指定对方的IP地址。
不可靠:指IP协议不能保证IP数据报准确地到达接收端。
Ipv4头部结构:
(4)TCP(传输控制协议),为应用层提供可靠的、面向连接的和基于流的服务。
(5)UDP(用户数据报协议),为应用层提供不可靠、无连接和基于数据报的服务。
(6)telnet(远程登录协议),使我们能在本地完成远程任务。
(7)OSPF(开放最短路径优先协议),是一种动态路由更新协议,用于路由器之间的通信,以告知对方各自的路由信息。
(8)DNS(域名服务协议),提供机器域名到IP地址的转换。
DNS是一个分布式的域名服务系统。众多网络客户端程序都使用DNS协议来向DNS服务器查询目标主机的IP地址,其查询和应答报文如下图:
3、http(超文本传送)协议详解
它定义了浏览器(万维网客户进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。万维网的工作流程如下图所示:
用户在点击鼠标链接某个万维网文档时,http协议首先要和服务器建立TCP链接,使用三次握手,当三次握手的前两部分完成后,万维网客户就把http请求报文作为三次握手的第三个报文的数据发送给万维网服务器。服务器收到http请求报文之后,就把所请求的文档作为响应报文返回给客户。
http/1.0主要缺点是每请求一个文档就要有两倍RTT的开销,另一个开销是万维网客户和服务器每一次建立新的TCP链接都要分配缓存和变量,当万维网服务器同时要服务于大量客户的请求时,这会使万维网服务器的负担很重。
http/1.1解决了上述问题,它使用了持续连接,即万维网服务器在发送响应后仍然在一段时间内保持这条连接。
http协议本身是无连接的,通信双方在交换http报文之前不需要先建立http链接;http协议是无状态的,同一个客户第二次访问同一个服务器上的页面时,服务器的响应与第一次被访问时的相同(假定现在服务器还没有把该页面更新),这使得服务器容易支持大量并发的http请求。
http请求报文的一些方法:
http与https的区别
https是安全超文本传输协议,使用的端口是443,与http的明文传输不同的是,它是由ssl+http协议构建的可进行加密传输、身份认证的网络协议。
http状态码的含义表:
cookie和session的区别
cookie:
在客户端保持状态,将cookie附在请求资源的http请求头上发送给服务器(不安全)(存储的数据不可以超过4k)。
session:在服务器端保持状态,服务器用一种类似于散列表的结构来保存信息,给客户端返回一个session id保存于cookie,当cookie被人为禁止时,使用url重写/表单隐藏字段将session id送回服务器(服务器性能不好)。
------->统一资源定位符URL
<协议>://<主机>:<端口>/<路径>,里面的字母不分大小写
在百度输入网址后,都发生了什么
(1)浏览器分析链接指向页面的URL;
(2)浏览器向DNS请求解析www.baidu.com的IP
(3)域名系统解析出百度的IP是……
(4)浏览器与服务器建立TCP链接
(5)浏览器发出取文件命令
(6)服务器给出响应,将文件发送给浏览器
(7)释放TCP链接
(8)浏览器显示index.html中的所有文本
4、封装与分用
(1)封装
如上图所示,展示的是上层协议通过封装使用下层协议提供的服务,应用程序数据在发送到物理网络之前,将沿着协议栈从上往下依次传递。每层协议都将在上层数据的基础上加上自己的头部信息,以实现该层的功能。
如上,经过数据链路层封装的数据称为帧,帧才是最终在物理网络上传送的字节序列。如下图展示了以太网帧的封装格式:
(2)分用
当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中本层负责的头部数据,以获取所需的信息,并最终将处理后的帧交给目标应用程序,这个过程称为分用。分用是依靠头部信息中的类型字段实现的。如上图,展示了以太网帧的分用过程。
IP协议、ARP协议和RARP协议都使用帧传输数据,所以帧的头部需要提供某个字段来区分它们,以以太网帧为例,它使用2字节的类型字段来标识上层协议;同样,因为ICMP协议、TCP协议和UDP协议都使用IP协议,所以IP数据报的头部采用16位的协议字段来区分它们;TCP报文段和UDP数据报则通过其头部中的16位端口号字段来区分上层应用程序,我们可以通过在/etc/services文件中找到知名应用层协议使用的端口号,这里列举几个常用的端口号,DNS(53)、HTTP(80)。
帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务。
总的来说,在顶层目标服务看来,封装和分用似乎没有发生过。
5、TCP协议详解
(1)面向连接、字节流、可靠传输
TCP连接是全双工的,即双方的数据读写可以通过一个连接进行。
TCP模块发送出的TCP报文段的个数和应用程序执行的写操作的次数之间没有固定的数量关系。应用程序执行的读操作的次数和TCP模块接收到的TCP报文段的个数之间没有固定的数量关系。综上,发送端执行写操作的次数和接收端执行的读操作的次数之间没有任何关系。这就是字节流的概念。
TCP采用发送应答机制和超时重传机制,并且TCP协议会对接收到的TCP报文段(以IP数据报发送)重排、整理、再交付给应用层。
(2)TCP头部结构
16位端口号:客户端通常使用系统自动选择的临时端口号,而服务器则采用知名服务端口(/etc/services)。
32位序号:一次TCP通信过程中某一个传输方向上的字节流的每个字节的编号。
32位确认号:用作对另一方发送来的TCP报文段的响应,其值是收到的TCP报文段的序号值加一。
(3)TCP状态转移图
三次握手,四次挥手:
客户端通过connect系统调用主动与服务器建立连接,connect系统调用失败的原因可能如下:
1)若connect连接的目标端口不存在,或者该端口仍被处于time_wait状态的连接所占用,则服务器将给客户端发送一个复位报文段,connect调用失败;
2)若目标端口存在,但connect在超时时间内未收到服务器的确认报文段,则onnect调用失败。
TIME_WAIT状态存在的原因:
1)可靠的终止TCP连接;
2)保证让迟来的TCP报文段有足够的时间被识别并被丢弃。
TCP超时重传:
为每个TCP报文段都维护一个重传定时器,该定时器在TCP报文段第一次被发送时启动,若超时时间内未收到对方的应答,TCP模块将重传TCP报文段,并重新设置定时器,
TCP拥塞控制:
为了提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。提出了拥塞控制。
拥塞控制的最终受控变量是发送端向网络一次连续写入(收到其中第一个数据的确认之前)的数据量,我们称为SWND(发送窗口),SWND限定了发送端能连续发送的TCP报文段数量。这些TCP报文段的最大长度(仅指数据部分)称为SMSS,发送端要合理选择SWND的大小,若太小,则会引起明显的网络延迟;反之,若太大,则会导致网络拥塞;接收方可通过其接收窗口(RWND)来控制发送端的SWND,但仅仅通过RWND是显然不够的,所以发送端引入了一个称为拥塞窗口的状态变量(CWND)。实际的SWND值是RWND和CWND中的较小者。
拥塞控制包括四个部分:慢启动、拥塞避免、快速重传、快速恢复
先来讨论发送端未检测到拥塞时所采用的积极拥塞避免方法:
TCP连接建立好之后,CWND被设置为初始值1W,大小为2——4个SMSS。此后,发送端每收到接收端的一个确认,其CWND就被设置为CWND+=min(N,SMSS),其中N是此次确认中包含的之前未被确认的字节数。慢启动算法的理由是,TCP模块刚开始发送数据时并不知道网络的实际情况,需要一种试探的方式平滑地增加CWND的大小。
但是,如果不施加其他手段,慢启动必然使得CWND很快膨胀,因此TCP拥塞控制中定义了另一个重要的状态变量-----慢启动门限(ssthresh),当CWND的大小超过了该值时,TCP拥塞控制将进入拥塞避免阶段。拥塞避免算法使得CWND按照线性方式增长,主要有两种实现方式:
1)每个RTT时间内按照式CWND+=min(N,SMSS)计算新的CWND,而不论该RTT时间内发送端收到多少个确认;
2)每收到一个对新数据的确认报文段,就按照CWND+=SMSSSMSS/CWND来更新CWND。
再来讨论发送端检测到拥塞发生(可能发生在慢启动或者拥塞避免阶段)时拥塞控制的行为:
发送端检测拥塞发生的依据:
1)传输超时;
2)接收到重复的(3个)确认报文段;
对于第一种情况,依然采用慢启动和拥塞避免,执行重传并做调整:ssthresh=max(FlightSize/2,2SMSS) CWND<=SMSS,其中FlightSize是已经发送但未收到确认的字节数;对于第二种情况,则采用快速重传和快速恢复(若第二种情况发生在重传定时器溢出之后,则也当做第一种情况),当收到第3个重复的确认报文段时,按照ssthresh=max(FlightSize/2,2SMSS)计算ssthresh,按照式CWND=ssthresh+3SMSS计算CWND,并立即重传丢失的报文段;每收到一个重复的确认,设置CWND=CWND+SMSS,此时发送端可以发送新的TCP报文段;当收到新数据的确认时,设置CWND=ssthresh;此时,拥塞控制将恢复到拥塞避免阶段。
6、基本TCP套接口编程
Socket与TCP/IP的关系:
数据链路层、网络层、传输层协议是在内核中实现的,因此操作系统实现了socket系统调用来使应用程序能够访问这些协议提供的服务。由socket定义的这一组API提供如下两点功能:(1)将应用程序数据从用户缓冲区中复制到TCP/UDP内核发送缓冲区,以交付内核来发送数据(send函数);(2)应用程序可以通过它们来修改内核中各层协议的某些头部信息或其他数据结构,从而精细地控制底层通信的行为。
判断大端or小端:
现代pc大多采用小端字节序,因此小端字节序又称为主机字节序。大端字节序又称为网络字节序。
(1)socket函数
#include
int socket(int family,int type,int protocal);
socket函数在成功时返回一个小的非负整数值,与文件描述符类似,称为套接字。
(2)connect函数
TCP客户用connect函数来建立一个与TCP服务器的连接。激发TCP的三次握手
#include
int connect(int sockfd,const struct sockaddr *servaddr,socklen_t addrlen );
(3)bind函数
对于TCP调用bind函数可以指定一个端口号,指定一个IP地址。
(4)listen函数
(5)accept函数
由TCP服务器调用,从已完成连接队列的头部返回一个已完成连接。若已完成连接队列为空,则进程睡眠。
exec函数系列