TCP/IP架构就是IP、TCP、HTTP、TELNET、SNMP等协议的集合
主要用于互联网和局域网
由于其应用广泛
可以说,互联网协议 就是 TCP/IP,TCP/IP 就是 互联网协议。
除此之外,还有一些网络体系架构:
比如:
AppleTalk 用于苹果公司现有产品的局域网(仅限苹果公司设备使用)
IPX/SPX:用于个人电脑局域网等
美国国防部希望有这样一种通讯系统:
即使某处线路遭到攻击,也可以用迂回的方式保持通讯。
分组交换技术,使得多个用户同一时间共享一条线路。(ARPANET)
UNIX操作系统 使TCP/IP 广泛被接受。
作者:车小胖
链接:https://www.zhihu.com/question/66528743/answer/250078635
来源:知乎
据不可靠消息,杨贵妃不仅爱吃荔枝,还爱吃海南岛的香蕉,
为了让爱妃吃得开心,皇上命令大臣日夜兼程从海南岛运香蕉到长安。
香蕉如何从海南岛运到长安呢?
首先,要用船将香蕉运出岛,运到广东的码头。
然后从广东码头,士兵快马加鞭运香蕉向西北方向奔去。
跑着跑着,遇到了长江,必须换乘船只运送,难道让马飞过去、或游过去?
到了长江北,继续快马向西北奔去…
跑着跑着,遇到了淮河,又要换乘轮船了,不换行不行,肯定不行!
到了淮河北,继续快马向目的地“长安”奔去…
最终,香蕉到达目的地,成了杨贵妃的美餐…
如果把士兵比喻成IP包,
则马、船只就是数据链路层,
为何IP包每一跳需要更换数据链路层,就如同士兵需要不断变换交通工具一样自然,形势所迫啊!
问同学们一个问题:为何士兵要将香蕉向北运到广东?而不是向南运到澳洲?
同学们一定会哈哈笑,这还要问吗?因为广东更靠近杨贵妃!
下一个问题是:为何士兵不直接奔向长安?而是先到广东码头?
同学们一定会回答:码头是必经之地,码头是通向目的地长安一块跳板,
尽管不是最终的目的地,但士兵(IP包)却需要经过它。
如果有飞机,士兵一定直飞西安,而不会再绕到广东码头,在这里,飞机同样是数据链路层,
因为它的目的是服务士兵(IP包),而士兵携带着最终的目的地:西安!
从点开一个网址开始,到浏览器显示内容…
数据可整整经历了一个往返:
具体来说:
HTTP协议就是:
规定了请求和应答消息的格式:
请求消息包括请求行(方法、URI、HTTP版本)、消息头和消息体
响应消息包括状态行(HTTP版本、状态码、响应短语)、消息头和消息体
客户端向服务器发送 请求消息
服务器收到消息后对客户端 响应
浏览器先要生成请求消息,并 委托操作系统(TCP/IP协议栈) 发送
请求消息主要说了两件事:“对什么”和“进行怎样的操作”
“对什么”:从网址URL中提取出URI,就是服务器的文件路径
“进行怎样的操作”指的就是Get和Post
当然,还要发送版本号、消息头和空消息体
服务器收到请求消息,会将请求URI转换为实际目录结构的实际文件名
这个文件要么是一个HTML文件,直接放到响应消息体中就行了
要么是一个CGI程序,我们运行这个程序,将结果放到响应消息体中
不过,在这些操作之前,浏览器也可以先根据需求检查一些请求包的参数
进行允许或禁止访问控制,常用的方法有三种:
①客户端IP地址
②客户端域名先根据客户端的IP向DNS服务器反向查询客户端的域名
为保险起见,再通过域名查询发送方IP地址,以防止客户端在DNS上注册假域名
如果两者一致,就允许访问③用户名和密码
首先,看一下Content-Type=text/html
根据MIME规格,可以确定这个响应,主类型是文本数据,子类型是HTML
之后,再看一下编码方式,charsrt=utf-8,以uft-8的字符编码显示网页
在客户端请求服务器之前,服务器应先正常运行
服务器要 购买域名,以确保自己的域名能在DNS服务器上找到
服务器在编程开发测试架设部署运维之后正式上线,这时,先要启动服务器:
PS:服务器需要接受客户端的请求,所以 服务器 就需要 先 进行准备工作,等待 客户端的连接
服务器需要同时和多个客户端通信,所以每当一个客户端连接进来,服务器就要 启动 一个 新的
服务器程序,这样服务器程序和客户端程序就是 一对一 的状态了。
如下图,当服务器程序启动并读取配置文件完成初始化操作后,就会运行 等待连接模块(a)
这个模块会 创建套接字,然后进入 等待暂停状态。
接下来,当有客户端发起连接时,这个模块会恢复运行并接受连接
然后启动 客户端通信模块(b),并 移交完成连接的套接字
接下来客户端通信模块(b)就和客户端进行通信,通信结束后,这个模块就退出了
上述这些过程,都是调用操作系统Socket库函数完成的,来看看调用的具体过程:
客户端通信模块需要经过下面4个阶段:
(1)创建套接字阶段
套接字 是 一块用于存放控制信息的内存空间
里面存着:通信对象的IP地址、端口号、通信操作的状态、发送数据经过了多长时间等
套接字创建完成后会返回一个描述符
描述符 是我们本机的应用程序识别套接字的编号,
协议栈内部找这段内存空间用描述符更快
而且在还没有建立连接的情况下,端口号和ip地址信息是不全的,只能使用描述符(2)连接阶段(用管道连接服务器端的套接字)(三次握手)
三个参数:
描述符:找到我方套接字
服务器IP地址和端口号:找到对方地址(服务器)以及对方的套接字(服务器上的应用)
IP地址和端口号 是客户端和服务器之间用来识别对方套接字的机制(3)数据收发阶段
(4)断开连接阶段(断开管道并删除套接字)(四次挥手)服务器或客户端,一方先调用Socket库中的close()程序,另一方也就断开了
服务器端在第(2)步有些不同:
(1)创建套接字阶段
(2-1)将套接字设置为等待连接状态bind()将端口号写入套接字,客户端要访问的端口号就是在这一步设置的
Web服务器使用80端口号
listen()向套接字写入等待连接状态(2-2)接受客户端的连接
accept()函数执行,开始等待客户端connect()的包到达(等待连接模块(a))
一旦客户端的包到达,就会返回响应包并开始接受连接的操作
协议栈会给等待连接的套接字复制一个副本
然后将连接对象等控制信息写入新的套接字中
以后,这个新的套接字就和客户端的套接字连接在一起了
而原来处于等待连接的套接字,会再次调用accept()
ps:如果不创建副本,而是直接让客户端连接到等待的套接字上,
那就没有其他套接字等待连接了,所以复制副本是必要的
但是,这又出现了一个问题:
端口号是用来识别对方套接字的
以前我们说,不通套接字应该对应不通端口号
但在服务器端,套接字都是80端口号
所以,在服务器端,客户端不能仅靠端口号来识别服务器的套接字
而是使用:客户端IP,客户端端口号,服务器端口号,(服务器IP),这3(4)项来识别服务器的套接字(3)数据收发阶段
(4)断开连接阶段(断开管道并删除套接字)
这里以接收为例,发送过程相反
网卡:
接受到电信号\光信号,将其还原为0\1数字信息
还原成的数字信息如下:
MAC模块:
接下来根据包末尾的FCS来检验错误,如果错误就丢弃
如果没错,看看MAC地址是不是自己的,如果不是,就丢弃
如果是,存储到网卡内部缓存区
通过中断通知CPU
然后网卡驱动开始运行,从缓存区读出收到的包
根据MAC头部判断是不是交给IP协议
IP模块:
IP模块检查校验后,看看IP是不是给自己的
如果服务器启动了类似路由器的功能,则对不是给自己的包,也会进行转发
如果是自己的,看看有没有分片
如果分片了,就暂存在内存中,等所有分片全都到达后再组装成原始包
接下来检查IP的协议号字段,看看是给TCP还是UDP
TCP模块:
SYN=1 表示需要我接受连接,需要检查包里接受端的套接字
自己有没有等待连接的这个套接字
如果没有,就会向客户端返回错误通知的包
如果有,则复制一个新套接字副本
并将发送方IP地址、端口号、序列号初始值、窗口大小等必要信息写入套接字副本
同时分配发送缓冲区和接受缓冲区的内存空间
然后生成代表接受确认的ACK号、序列号初始值、剩余窗口大等来生成TCP头部
委托IP发送出去
这个包到达后,客户端会返回ACK号
当这个ACK后返回服务器,连接操作就完成了
http:// 指 使用http协议
www.lzu.edu.cn 经过 DNS 过程,得到服务器IP地址
/static/leader 你想要的文件或CGI程序(Servlet也是一种CGI程序,Servlet是Java代码)
URL可能还会带有参数,例如访问百度服务器:https://www.baidu.com/s?wd=风景
URL中还有一个隐藏信息:
如果是 网页链接、图片和超链接,都是默认会使用HTTP协议的 Get 方法
Get方法的一个明显特点是后面还可以 带参数
如果是 表单提交,Method 可以选择 Get 或者 Post
以上就是能从URL网址中得到的信息。
ps:HTTP请求,怎么判断get提交还是post提交?
最直观的方法是观察 地址栏参数 是否 显式传值,参考: HTTP请求,判断get提交还是post提交的方法.
一般来说,当你想获取一些资源,比如图片、网页、脚本、样式文件,就是GET,这个是固定的
举例:
你在浏览器输入 http://sf.gg/ 就是 GET
浏览器打开了http://sf.gg/,页面左上角有个logo也要请求下来显示, 也是GET
当你要提交一些数据给服务器,由服务器处理或者保存,就是POST
这个是由HTML代码指定的,浏览器只是严格按照指令执行
表单提交的话可以在method这个属性中指定提交方式;如果是ajax请求,可以在type选项中指定
但现如今网站传值都使用POST,get容易产生SQL注入。
<form id="Form" action="" method="post">…form>
地址包括网络号和主机号
ps1:实际上
A类地址网络号只能1.0.0.0-126.255.255.255
B类地址网络号只能128.1.0.0-191.255.255.255
C类地址网络号只能192.0.1.0-233.255.255.255
E类只能240.0.0.0-255.255.255.254
0.0.0.0; 127.0.0.0-127.255.255.255; 255.255.255.255;
128.0.0.0-128.0.255.255 ;192.0.0.0-192.0.0.255 ;169.254.0.0-169.255.255.255; 都是特殊的
ps2:主机号全0表示本网络,全1表示广播地址
ps3:私有地址:
A类:1个网段,10.0.0.0-10.255.255.255
B类: 16个网段,172.16.0.0-172.31.255.255
C类: 256个网段,192.168.0.0-192.169.255.255
路由器对私有地址一律不转发
NAT路由器:私有地址和共有地址的转换
普通路由器转发IP数据报时,不改变源IP和目的IP,
但NAT路由器一定要转换其源IP或目的IP
ps4:D类组播地址:
使用这一类地址,属于某个组的机器都能收到,
这有点类似在公司里面大家都加入了一个邮件组。发送邮件,加入这个组的都能收到
人们慢慢意识到,IP地址已经不够了
当时,A类地址已经耗尽,B类也快用完,只有C类地址还有剩余
但是C类地址才能分配254台主机啊
所以,我们需要一个更加灵活划分子网的方式
而不是依赖8位、16位或者24位网络号
这样,ISP或管理员就能够把多个连续C类地址聚合
比如:一个ISP可以分配
204.21.128.0 (1100 1100 0001 0101 1000 0000 0000 0000)~
204.21.255.255(1100 1100 0001 0101 1111 1111 1111 1111)
它们前17位是一样的,因此此超网为204.21.125.0/17
CIRD可以用在公网地址,也可以用在私网地址。
操作系统Socket库中,有DNS解析器这一程序组件
浏览器调用这个库的函数,
假如为 x=gethostbyname(“www.baidu.com”);
就可以得到服务器的IP地址。
gethostbyname{
发送生成给DNS服务器的查询消息;
调用UDP协议栈发送(UDP通过网卡向服务器发送,DNS服务器的IP地址我们已通过配置指定);
(等待)从UDP协议栈接收从DNS服务器服务器返回的响应消息;
取出需要的ip地址;
return 浏览器;
}
可以参考我的这篇博文:链接: Socket是个啥?.
这篇文章,我对Socket有这样的理解:
应用程序需要通信,就会调用操作系统名为Socket库的某些函数,
第一步是调用Socket库的某个函数 创建Socket
通过一段程序代码,Socket就创建出来了
但到底创建了啥呀?
答案是:创建了 一块用于存放控制信息的内存空间
里面存着:通信对象的IP地址、端口号、通信操作的状态、发送数据经过了多长时间等
系统给它一个ID以便可以定位到它(描述符/端口号)
有了它,我们就可以继续调用Socket库中的其他函数:
建立连接函数、发送数据函数、接收数据函数、断开连接函数
将Socket作为这些函数的参数
协议栈根据这些参数,判断下一步的行动:
举个例子:write(
当你往write函数里写东西的时候
操作系统(的协议栈)就不断读套接字信息和要发送的数据(当然也是按排队的顺序读的),
去控制硬件,进行通信
之后你再写,操作系统再读
直观看一下套接字吧:
这里的每一行就是一个套接字!
关于netstat命令,可以参考我的这篇博文:
链接: 电脑的危险端口?135,137,139,445,3389.
网上还有一些形象的比喻:
①可以把进程(某正在运行的程序)想象成一个房子
套接字就是我们安装的一个门,这就是创建套接字操作
我们还要修建一条路连接两个门,这就是建立连接操作
这样就可以进行通信了
用五层协议来看,Socket是应用层和传输层之间接口
前面我们说,应用程序调用操作系统的Socket库,
所以,套接字也称为应用程序与网络之间的 应用程序编程接口(API)
②下图,将管道的出入口类比为套接字,数据通道是双向的:
这里,要发送的数据就是HTTP报文了
浏览器进行上图的操作:创建套接字、connect、write、read、close等
而这些函数的细节后面再讲
这里只是调用部分
这些函数都是Socket库中的程序组件
浏览器如上图,
按照指定的顺序来调用Socket库中的程序组件
以向操作系统的协议栈发出委托
套接字创建完成后会返回一个描述符,
描述符:是我们本机的应用程序识别套接字的编号
三个参数:
描述符:找到我方套接字
服务器IP地址和端口号:找到对方以及对方的套接字
IP地址和端口号:是客户端和服务器之间用来识别对方套接字的机制
下一章节详述
服务器或客户端,一方先调用Socket库中的close()程序,另一方也就断开了
上一小节,浏览器通过调用操作系统Socket库中的函数来调用协议栈
这节来看看协议栈具体的操作
时延 指的是数据(一个报文或分组)从网络(或链路)一端传送到另一端所需要的总时间。
时延由4部分组成:发送时延、传播时延、处理时延和排队实验
通俗来讲就是数据从电脑到网线口
也就是从发送数据的第一个比特算起,到该帧的最后一个比特发完为止所需要的时间
上面说的发送缓冲区的等待就属于发送时延
发送时延=数据块长度(bit)/信道带宽(bit/s)
ps:我们一般换好的网卡、换千兆网口、换网线,就是为了提高发送时延
传播时延=信道长度(米)/信号(电磁波)在信道上的传播速率(米/秒)
比如分析分组首部、从分组中提取数据部分、进行差错校验或者查找适当的路由器等
路由器确定转发端口后,还要在输出队列中排队等待转发
ps1:做题时,排队时延和处理时延可以忽略不计
ps2:高速链路,提高的仅仅是数据发送速率而不是比特在链路上传播的速率,因此是减少发送时延
ps3:关于处理和排队时延,可以选择更加高性能的路由器
ps4:光纤比网线快?并不是,光纤和网线的传输速率都是光速
①传数据容量:但光纤支持带宽大,一般网线支持带宽最大到1G(近似1000M)
而光纤本身支持带宽则为数G甚至数十上百G
所以,如果所传输数据非常庞大,则光纤有很大优势
能在较短时间内,传输完较大数据(数据超过1G情况)
②发送和接收:现在的电子系统(比如计算机,比如服务器),只能识别电信号,无法直接识别光信号
所以,网线可以直接连接电子设备,而光纤则必须通过光电转换器转换为电信号后再被电子设备识别
因此,在传输数据量比较小情况下,两者虽然速度一样(估计几纳秒的差异你也看不出来)
但光纤的延时会比单纯的网线要高一些
所以,这种情况从理论来讲,反而网线速度快
③距离:网线传输,受电气损耗影响,一般距离较短(一般最高也就百米的单位)
而光纤距离至少也是2Km(多模),甚至几十,上百千米的
综上:现在多数情况下的网络建设都是光纤作为主干通信线缆而网线作为末端连接电子设备的通信线缆
有 b/s bps kb/s(k=103) Mb/s(k=106) Gb/s(k=109)
ps:限制吞吐量最大因素?
从服务器到端的下载,包经过多个路由转发,每条路由线路的速率都是不相等的,吞吐量取决于 Min{v1,v2,v3},但是,核心网的传输速率是高速的,就像一个巨大的管道,所以,今天因特网中对吞吐量的最大限制因素是——接入网(Min{服务器接入网,客户端接入网})。
辨析:宽带与吞吐量:
带宽和吞吐量的单位都是bps
但带宽是指ISP描述自己提供线路的,吞吐量时用户实时描述自己计算机性能的
由于受到各种影响,吞吐量会小于带宽。
辨析:宽带与带宽:
带宽是量词,指的是网速的大小,比如1Mbps的意思是一兆比特每秒,这个数值就是指带宽。
宽带是名词,说明网络的传输速率速很高 。
宽带的标准各不相同,最初认为128kbps以上带宽的就是宽带,而以下的就是窄带。
但现在国内运营商一般提供至少512kbps带宽的宽带服务。
也就是说,带宽是一个具体的数值,而宽带则是满足一定带宽数值的一种传输标准(服务)。
发送端已经发出的比特数,
链路指一个圆柱形管道,长度代表传播时延,横截面代表链路带宽
时延带宽积表示该链路可以容纳的比特数量
所以,时延带宽积又称为以比特为代为的链路长度
并非越高越好
数据容量容量:1024; 1GB内存=102410241024B
CPU频率速度单位:1000;1GHz=100010001000Hz(次每秒)
网络传输速度单位:1000;20M带宽=20Mbps=20100010008bps=20/8MBps=2.5MB/s
ps:买了一块500G硬盘,生产商按1000算,500×1000×1000×1000/1024/1024/1024G=466G
ps:百兆网口和千兆网口说的是带宽
100M带宽=100Mbps=100/8MB/s=12.5MB/s(实际在11M左右)
1000M带宽=1000Mbps=1Gbps=1000/8MB/s=125MB/s(实际在16M左右)
注意:下电影取决于视频平台服务器的上传速度,说明16M/s已经到达瓶颈了,你就是万兆宽带也是一样
创建套接字时,首先分配一个套接字所需的内存空间
然后向其中写入初始状态
这个函数返回一个描述符
应用程序收到描述符后
应用程序再向协议栈进行收发数据的委托时
就提供这个描述符,即可定位到socket的位置
这里我们可以将其理解为“准备”
就是通信双方交换控制信息,在套接字中记录这些必要信息,
并准备数据收发的一连串的操作(比如申请两块内存空间——接收数据缓存区和发送数据缓存区)
(控制信息分为两类:一类是头部信息:TCP的SYN、ACK、序号、窗口大小等,
另一类是套接字信息:包括从应用程序传来的信息、从通信对象接收到的信息、收发数据操作的执行状态信息等,如IP地址、端口号、连接状态等,协议栈会根据这些信息执行每一步操作)
具体操作过程:其实就是TCP的三次握手过程:
第一次握手(客户端到服务器):发送SYN=1、源目标端口号等头部信息
服务器收到客户端的信息,找到自己的套接字,改为正在连接状态
第二次握手(服务器到客户端):返回SYN=1、ACK=1、源目标端口号等头部信息
客户端收到服务器来的信息,收到SYN=1,表示连接成功,
向套接字写入服务器的IP地址、端口号等信息,将状态修改为为已建立连接
第三次握手(客户端到服务器):返回ACK=1,告诉服务器第二次握手我已收到
服务器收到,修改状态为已建立连接
关于序号和窗口大小,将在下一小节讲述
ps:需要注意的是:TCP每一次握手传输的数据,也要经过网络层、数据链路层和物理层:
连接已成功,接下来客户端将HTTP请求消息交给协议栈,也就是调用write()函数
协议栈并不关心应用程序传来的程序是什么
write()函数的一个参数指定了要发送内容的长度
所以,对协议栈来说,要发的数据就是一定长度的二进制数而已
协议栈收到了这段内容,它不是立刻发送
而是将这段内容放到<发送缓冲区>,并等待下一段数据
这样可以避免发大量的小包,导致网络拥塞
协议栈等待时间的设置需要考虑两点的平衡:容量和等待时间
一是每个包能容纳的数据长度:
以太网的MTU是1500字节,
MTU去掉IP、TCP头部和FCS校验就是MSS
等缓冲区接近MSS时,就可以避免发送的包过小了
TCP协议栈等到MSS
HTTP请求消息一般不会很长,一个网络包就装得下
但如果要提交表单,比如一篇长文
这种情况下,发送缓冲区中的数据就会超过MSS
这时,协议栈会以MSS切分数据发送
接着上面,第二点需要考虑的等待时间:
当应用程序发送时间不高时,如果每次都等MSS的时候再发送
那延迟(发送时延)可就太高了,这种情况下
即便缓冲区没到MSS,也要及时发送出去
协议栈内部有一个计时器
当经过一段时间后,就不管其他的,直接发出去
前面说到,网络包已经装好数据从客户端发往服务器了
服务器接收到数据包后,需要发送确认信息,
否则,客户端就会以为网络包丢失了,会进行重发
过程如下:
首先:TCP拆分数据,以从头开始的字节数作为"序号seq",放在TCP报头里
发送方的IP报头里有IP报头的长度和总长度,两者相减就是TCP的总长度
由于TCP头部长度固定吗,就可以算出TCP数据长度
接收方就可以知道发送的数据是从第几字节开始的,长度为多长
就可以计算出,下一次的seq为多少
下一次如果对上了,就继续接受,并加起来
接受方就得到目前为止,一共接收了多少字节,并发送回去
这里简单说明一下上图:
上图中,实际上序号不是从1开始的,这样容易被黑客攻击
seq在连接三次握手阶段确定
上图的对话过程是:
客户端:请给我XXX数据
服务器:现在发送1字节开始,共1460字节
客户端:到1460之前已收到,该给我1461了
服务器:现在发送1461字节开始,共1460字节
客户端:到2920之前已收到,该给我2921了
实际上,TCP是双向通信的:
双方的序号初始值由自己确定告诉对方
所以,实际的工作状态如下:
在发送阶段,TCP采用这样的方式确认对方是否收到了数据
在得到对方确认之前,发送过的包都会保存在发送缓冲区中
如果对方没有返回某些报对应的ACK号,那么久重新发送这些包
所以,TCP是可靠的,无论网络中发生任何错误,我们都可以重传保证
网卡、集线器、路由器都没有这样的补偿措施,一旦检测到错误就直接丢弃
ACK号还有一些技术:
第一是根据网络包平均往返时间调整ACK号的等待时间(超时时间):
也就是,多久没有收到ACK包,我们就认为包丢失了
这里就是避免拥塞的一些方法
但我们知道,这个值肯定是动态的,
如果网络拥塞,就时间长一点
否则,重发ACK会导致网络更加拥塞
第二是使用窗口有效管理ACK号:
没发送一个包就等待一个ACK号很容易理解
但是,在等待ACK号的这段时间
如果什么也不做傻等着那可就太浪费了
所以我们决定:在发送一个包后,不等待ACK号返回,
直接发送后续的一系列包
这样,等待ACK号的这段时间就被利用起来了
但是,可能会因为发送方的包太多而接收方处理不过来的情况
具体来说:当接收方收到TCP包后,会首先将它们放到接收缓存区
然后,接收方需要计算ACK号,将数据组装起来还原成原本数据并传递给应用程序
但是,如果处理这些的时候,接收缓存区满了,接收方就会丢弃了
为了避免这种传输浪费,接收方应告诉发送方,自己的缓冲区容量还剩多少
这就是滑动窗口大小,如下图:
注意:
滑动窗口与接收缓存区是双向的
ACK与窗口信息也可以合并:
先说窗口:当接收到的数据刚进入缓存区的时候
其实没必要每次都向发送方跟新窗口大小
因为发送方根据以前的窗口大小减去自己发送的数据
就可以计算出还剩多少窗口
所以,更新窗口的时机应该是:
接收方从缓冲区取走数据的时候
ACK号是只要确认收到,就应该马上返回
所以,当要发送ACK号的时候,正好需要更新窗口,
就可以将它们放在同一个包里发送
当需要连续发送多个ACK号的时候
可以只发送最后一个ACK号
因为ACK号表示目前已收到的数据最后的位置在哪里
当需要连续发多个窗口更新时,也可以省略中间过程
发送最终结果就可以了
具体操作过程:其实就是TCP的四次挥手过程:
四次挥手知识点这里.
为什么要四次挥手点这里.
其实不管三次还是四次,其实就是干了两件事: 你发送我确认,我发送你确认
因为TCP是全双工的,所以三次握手就是:
客户:开始
服务器:收到
服务器:开始
客户:收到
四次挥手就是:
客户:结束
服务器:收到
服务器:结束
客户:收到
而三次握手为了减少网络开销,将收到和开始合并了而已
服务器或者客户端一方先调用Socket库中的close()函数
假定是服务器先断开,
服务器的头部就先发送断开的TCP:FIN=1
客户端收到服务器发来的FIN=1
就将自己的套接字标记进入断开操作状态
然后为了告诉服务器我收到了
返回一个ACK
这是,应用程序可能会调用read()来问协议栈要数据
如果接收缓冲区还有剩余的已接受数据,就给应用程序
如果没有,就告诉应用程序,所有的数据你都已经收到了
这时,客户端就会调用close(),同样发送FIN=1
服务器收到,返回ACK,服务器等一段时间再真正关闭,删除套接字
而客户端收到服务器的ACK就立即关闭,删除套接字。
ps:为什么发起FIN的端要等待2MSL呢?
如下图,如果不等待,直接关,
对面就会重发FIN
如果这个套接字又新分配出去
就会发生错误
最早TCP和IP协议是合在一起的一个协议,后来才拆分成两个协议,
这就是为什么这两个协议联系这么紧密的原因
TCP模块在执行连接、收发、断开等各阶段操作时
都需要委托IP模块将数据封装成包发送给通信对象
这一部分,我们来讨论IP模块是如何将包发送给对方的
上面,我们可以看到TCP被包了两个头部:
IP模块负责添加如下两个头部:
一个是IP头部:IP用头部,包括目的IP地址
一个是MAC头部:以太网用头部,包括MAC地址
这两个头部有着不同的作用
我们具体看例子:
客户端发的数据包括IP头部和Mac头部
IP地址为服务器IP地址,而MAC地址为下一跳路由器R1的地址
第二个设备不管是集线器还是交换机,都只是进行端口转发,不改变MAC头部和IP头部
而经过路由器改变MAC头部,不改变IP头部
交换机里有一张表,用来判断从哪个端口出
路由器有路由器表,根据表格查询应该发往哪个IP,再根据这个IP查询出下一跳MAC地址,进行改写MAC头部
值得注意的是,IP包头的协议号字段填写了上层模块:如TCP、UDP
MAC包头的以太类型字段填写了里面包裹着哪种协议:如IEEE802.3、IP协议、ARP协议、IPv6协议等
由于IP的分片,服务器需要接受到所有IP并进行重组后,再发给上层传输层
ps1:有了MAC地址为什么还需要IP地址呢?
MAC地址,比如00-16-EA-AE-3C-40,不好划分网络号主机号,不好管理
这就好比,你已经有了手机号,为什么还要一个身份证号呢?
ps2:有了IP地址为什么还需要Mac地址呢?
IP和以太网的分工,以太网的部分可以替换成其他东西:例如无线局域网、ADSL、FTTH,
它们都可以代替以太网的角色帮助IP协议来传输网络包。
分为两层,可以更好地根据需要使用各种通信技术,增加了灵活性。
https://blog.csdn.net/Shuffle_Ts/article/details/93522850
报文到达每一层,首先验证校验和是否正确,丢弃掉不正确的报文,再才会进行后续操作
这里以IP校验为例:
验证:取反相加!=相加取反
3 22C4
22c4 10001011000100 取反:01110100111011
0003 11 取反:00
22c7 10001011000111 取反:01110100111000
取反相加=相加取反 不成立!
!(22c4+0003)=01110100111000
!22c4+!0003= 01110100111011+00
3 22C4
~ 22C4
---------------
3 FFFF
3 22C4
~ 22C4 ~11 ✖ 分配率不成立
~ 22C7 下面比上面大3,取反后,下面比上面小3
---------------
所以需要,再加上3,正好FFFF
双绞线抑制噪声,传输距离100米
百兆网口用13发送,26接收,采用差分信号
千兆网口用1236发送,4578接收
收到信号后广播到所有连接的设备且不进行MAC校验
由设备自己判断应该接收哪些包和进行FCS数据链路层检验
集线器是物理层和MAC层设备,它不具备学习和记忆功能
只有PHY(MAU)(用来发送和接收信号的电路)
所以连接在集线器上的主机引入了 载波帧听多路访问/冲突检测协议(CSMA/CD协议)
载波监听:就是发前听,又非坚持、1-坚持、p-坚持算法
多路访问:就是公用一条总线,分为信道划分协议、随机接入协议和轮流协议,这里用的是随机接入
带冲突检测:就是发的时候还监听着
集线器所有端口1个冲突域,1个广播域
交换机的设计是将网络包原样转发到目的地
交换机的每个网口就相当于计算机的一块网卡
但是,交换机的所有口都不具有MAC地址
所以,交换机口在检验过MAC层的FCS正确后
不核实MAC地址直接全盘接收
将所有收到的包都放到缓冲区中
之后,再根据自己的对应表决定从哪个端口发送
交换机假设有12个端口,就有12个冲突域