局域网LAN:计算机数量多了,通过交换机和路由器连接在一起就形成了局域网(千米以内,最多几公里)
城域网:几十公里
广域网WAN:将远隔千里的计算机都连接在一起 互联网:国际的一个广域网
1. 协议概念
协议就是一种约定
通信双方约定好的网络通信数据信号的解析式
协议有三个要素组成:
2.协议分层
优点:
3.OIS七层参考模型
按照网络通信中的协议接口,服务对网络通信进行分层:
应用层:负责应程序之间的协议 http ftp 表示层:设备固有的数据格式和网络标准数据格式的转换。
会话层:通信管理。负责建立和断开通信连接(数据流动的逻辑逻辑通路
传输层:负责端与端之间的数据传输。负责可靠传输(确保数据可靠的到达目的地址)
网络层:地址管理和路由选择
数据链路层:互联设备之间的传送和识别数据帧。 物理层:负责光信号和电信号的传递方式。界定连接器和网线规格。以0 和1 代表电压高低灯光闪灭。
4.TCP/IP五层模型
TCP/IP是一组协议称之为TCP/IP协议簇,最典型的是TCP IP
应用层:负责应用程序之间的沟通。
http(超文本传输协议)、ftp(文本传输协议)、SMTP(电子邮件传输)、Telent(远程访问协议)
传输层:负责端与端之间的数据传输
(tcp udp) (数据如何传输)
网络层:负责地址管理和路由选择
ip; 路由器(路由选址,数据转发) 经过那个路由
链路层:负责相邻设备的数据帧传输
eth(以太网:规定数据的开始与结束) 交换机:数据转发 (网卡层) 数据帧:数据的不同叫法
物理层:负责光电信号的传输 (网线双绞线)
以太网协议:(网线的规格) 集线器(hub):(数据连接 ,信号放大)
同一个网段内的两台主机的进行文件传输
1.数据包的封装与分用:
不同的协议层对数据包的称谓不同,在传输层叫段 ;网络层叫数据报 ;在链路层叫帧
应用层数据通过协议转发到网络上时,每层协议都要加上数据首部,称为封装
首部信息包含 首部长度,载荷多长,上层协议是什么信息
数据封装成帧后传输到介质上,到达目的主机后每层协议剥掉相应的首部,叫分用 ;根据首部中的“上层协议字段”将数据交给对应的上层协议处理
通信流程:
1.应用层:应用协议 qq
2.传输层:udp tcp 端口之间的数据传输
3.网络层:ip协议 地址管理和路由选择
4.数据链路层:eth (帧头 帧尾)相邻设备之间的数据传输 (交换机)
1.ip地址:
a.通过DHCP自动分配(谁上网给谁分配)
b.ip地址替换(NAT) :(通过给路由器分配一个ip地址,路由器在接上一定数量的主机) 路由器进行地址转换
2.端口号
1.端口(Port):用于 唯一标识网络上处理数据的进程
为什么不用进程id ?
因为端口是写入程序中的固定的,而进程id是不固定的,用固定的数据确定进程
源ip、目的ip、源端口、目的端口、协议(sip dip sportd dortp proto) :标识一条通信
3.网络字节序:
字节序:cpu对数据存取的顺序 —存储大小大于一个字节的数据
大端字节序:低地址存高位
小端字节序:低地址存低位
大小端的详细解释:https://blog.csdn.net/qq_38810767/article/details/87621307
通信双方无法确定对方电脑的字节序的时候,发送大于一个字节存存储数据就有可能造成数据错误
解决方法:不管主机是大端还是小端,反正网络通信的时候同一使用大端字节序通信
网络字节序:就是统一字节序,大端字节序
主机字节序:当前主机字节序,不一定大端或小端,取决于cpu架构
大小端取决于cpu架构:
x86:小端
MIPS:大端
(类似于寄信)
无连接:知道对端的ip和端口就直接进行传输,不需要建立连接
不可靠:没有确认机制,没有重传机制,如果因为网络故障数据段无法发送到对方,udp协议层也不会给应用层发送任何错误信息
面向数据报:应用层交给udp多长的报文,udp原样发送,不会拆分不会合并
缺点:无法保证数据的安全传输
优点:传输快,没有粘包问题(因为udp头部有数据长度,而且每条数据都会加上udp头,再放入缓冲区中所以不会发生粘包问题)
使用场景:传视频,早期QQ, 广播。对于高速传输和时实性要求比较高的通信领域
协议中有:
udp的边界控制的特点:
udp数据包的长度,因为有这个长度,因此数据之间有了明显的边界,因此不会出现粘包问题
但是每个数据包的长度是有限的~不超过64k(2的16次方:65535)
数据的长度:为udp的len-8(头部长度)
传输大数据的时候,需要在应用层对数据进行切分
因为udp不可靠传输,所以无法保证安全也无法保证包序,就需要在应用层进行包序管理(例如:对数据进行切分,切分之后对数据进行编号);
优点:传输安全可靠
缺点:容易发生粘包问题,数据传输慢
场景:用于文件等对安全性要求比较高的数据,重要状态更新
tcp的socket也是全双工,能接受发送数据。
服务器长时间没有收到最后一个ack,不会超时重发syn+ack,而是直接发送重置连接到客户端。
防止最后的ack丢失导致对段重发fin包对新起的地址端口连接造成影响
因为最后一个ack丢失(或者因为网络状况不好导致在报文的最大生存周期之内)之后,对端没有接收到ack,因此重发fin请求;
假如没有这个等待时间,而直接重新启动应用程序,就有可能会接收到这个重发的fin包对新连接造成影响
第一个msl是主动关闭方最后ack的最大生存周期,第二个msl是重发fin包在网络上的最大生存周期,如果主动关闭方在两个msl时间后都没有接收到重发的fin请求,就可以关闭了,因为不管ack有没有成功,重发的fin都会消失在网络中。
如何确定对方收到数据
假如对方没有收到数据
超时重传机制:如果长时间没有收到ack回复就重新传输
这个时间:
随着网络环境是不同的,太长影响整体传输效率太短会频繁发送重复包
所以Linux是动态的计算这个时间,第一重发500ms,第二次等待2*500ms,每次判断超时重
发的时间都是500ms的整数倍。累计到一定的重传次数,tcp认为网络或对端异常,关闭连接。
如何保证数据的有序传输
确认序号:其实序号+传输的数据长度
每一个数据进行编号,即序列号
每一ack都带有对应的确认序列号(接受到哪些数据到哪儿了,下次从哪儿发) 校验和
连续发送窗口大小的数据:一次发送多条数据,集中等待(快速重传),
一次发送的数据有多少,取决于tcp协议的窗口大小,窗口大小双方会进行协商 窗口大小决定了tcp的传输的吞吐量,窗口不大于缓冲区大小
快速重传:如果发送方没有收到第一条数据,但是等到了第二条数据的ack,那么他就认为第一条也发送成功了,不需要重传,假如第一条数据丢了,接收方会连续发送三次ack第一条数据的,发送方收到三次重传请求就会进行数据重传,不用等到超时时间
为什么是三条?
考虑网络延时
作用:探测网络情况,防止一开始大量丢包
一开始的时候,因为窗口大小比较大,发送方发送的数据比较多,如果网络不好,就可能大量丢包,就需要重传,造成性能下降。
拥塞窗口:双发进行窗口大小协商后,发送方还有一个东西叫拥塞窗口,并且拥塞窗口的大小开始的时候非常小, 引入拥塞窗口机制,刚开始慢启动,然后指数增长,等增长到阈值(接近窗口大小),此时此时线性缓慢增长,当发现丢包认为网络阻塞,这时候拥塞窗口立刻下降到起始位置,在进行原来的增长
确认回复的时候,捎带确认序列号 : ack+确认序列号
减少重传,提高传输效率
将确认应答直接标记在即将发送的数据包内,那么这样不仅传输数据也对上条数据进行回复了 滑动窗口中的协议:
1.停止等待协议:发送方和接收发窗口都是1,所以传输数据,传输一条回复一条,在网络情况差的时候,防止丢包
一应一答(网络状况不好的)
2.回退n步协议:一次性发送多调数据,可能其中一条(2)丢了,但是接收方发送三次那一条(2)的ack,然后接受方接受到了后重传,重传那条(2)以后的所有数据。(网络状况不好的话,就容易降低效率)
3.选择重传:那一条数据丢了只传那一条,网络状况慢的情况慢的情况也能提升效率
16源端口\16位目的端口:从哪儿进程来,去那个进程去
32位序列号:发送方给每一个字节数据进行编号,即序列号
32位确认序列号:接收方每一ack都带有对应的确认序列号(接受到哪些数据到哪儿了,下次从哪儿发)
4位tcp报头长度:tcp头部有多少个32位比特位(4个字节);最大:15*4=60;实际20保留6位:为头部大小保留的字节
6位标志位:
16位窗口大小:设置传输数据的滑动窗口的大小,提高传输性能
16位校验和:发送端填充,CRC校验,接收端校验不通过,则认为数据有问题,此处的校验和包含tcp首部和数据数部分
16位紧急指针:标识哪些是紧急数据,需要优先处理
40字节头部选项:
收发数据灵活,但是会造成粘包问题
字节流发送数据先将数据放到缓冲区中,等待数据大小超过缓冲区,然后一次发送,对端接受的时候可能当成一条数据接收。
如何解决粘包问题?
数据定长、 特殊字符、TLV格式数据:就是一个结构体(数据类型,数据长度,数组【0】);
tcp内部有自己的保活机制,会定期询问对方是否断开连接,如果断开,自己也会释放连接。
发送端判断:操作系统连续发送多条数据后没有收到ack后,认为断开, 向进程发送SIGPIPE信号,进程使用默认处理方式(退出进程)
接收方:recv返回0(对端关闭,连接断开)
1.创建套接字
- int socket(int domain,int type,int portocol)
域 套接字类型 协议
2.为套接字绑定地址信息(对于客户端不建议手动绑定,不手动绑定 这样会降低失败的可能性)
3.向服务端发起连接请求
4.发送数据 /接收数据
5.关闭套接字
服务端:
1.创建套接字
socket
2.为套接字绑定地址信息(固定)
bind
3.开始监听
listen(int socket,int backlog)
listen baklog参数:
同一时间的最大的并发连接数 同一时间能够同时接收客户端连接请求数
4.获取连接成功的客户端socket
int accept(int socket ,struct socket *address,socklen_t address_len)
5.接收数据\发送数据
recvfrom sendto
6.关闭套接字
close