计网学习
OSI七层模型
- 物理层 网线 比特流
- 数据链路层 MAC网卡地址 帧
- 网络层 IP地址 路由方式 包
- 传输层 端到端TCP UDP TCP报文 UDP数据报
- 会话层 不同应用程序间会话
- 表示层 数据格式转换、压缩加密解密等
- 应用层 web应用
好处:隔层之间独立,灵活性好,易于实现维护、能促进标准化工作


补充 数据链路层 PPP

一次完整的http请求包括?
- 客户端建立与服务器的连接
- 客户端发送请求,包含请求头、请求行、请求体
- 服务端响应请求
- 客户端的浏览器根据响应做出相应渲染展示给我
- 断开连接
DNS是什么?
- 是一种域名和ip地址互相转换的分布式数据库
- 我们记 www.baidu.com 比较好记, 但是123.741.15.1就很难记
- 解析DNS通常先从浏览器缓存、系统缓存、路由器缓存等解析,缓存里实在没有再用域名服务器解析,并把结果存到系统缓存里
- 使用域名服务器解析,使用UDP协议,因为域名一般不超过512字节而且UDP快!!
DNS服务器的查询分为递归查询(局部dns服务器向根域名服务器一级一级往下查 我帮你找到答案) 迭代查询(你去问这个服务器吧) 一般是从.服务器->.com服务器->baidu.com->www.baidu.com告诉你
http长短连接的区别
HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。
- 短连接就是每次报文通讯就建立连接,通讯结束就关掉,对于服务器来说好管理,存在的链接都是有用的
- 长连接就是每次传输后不会自动断开,一般会设定一个断开时间,一般在web服务器侧定义(TCP不断 SSL也不断)
- http1.0默认短连接 1.1后默认长连接 1.1+要想短连接需要在请求中指明connection:close
粘包拆包问题
粘包拆包问题在数据链路层、网络层以及传输层都有可能发生。日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中。
- 粘包发生的原因:发送端Nagle 算法造成可能粘包 客户端收的比来的慢造成粘包
- 拆包发生的原因:客户端接收缓存区太小、一次发送的数据大于报文所能承受的最大值(MSS)
- 解决方案:用标识符分割、设定合理的消息长度(不足补0等)、数据包中增加头部信息维护消息长度
HTTP的请求方法
- get 获取资源
- post 提交表单或上传资源
- put 上传资源以替换某内容
- head 仅获取请求头,比如检查这个资源是什么格式
- delete 删除指定资源
- trace 返回请求信息,用于诊断
- options 列出所有支持的方法
- patch 部分更新资源,put的补充
- connect 通过代理服务器建立连接
get获取数据,暴露在url上,以?分割url和数据,以&分割参数,最大2k且不安全,而且一次TCP全部发送出去,会被主动缓存
post修改或上传数据,存在于html的body里,安全,理论上无长度限制,两次TCP先发请求头响应100再发数据,默认不会被缓存
get 是幂等的(对同一url的多次请求得到的回复都是一样的)因为他不会改变资源,而post不是幂等的,所以不能用get增删改查
- get写法可以自定义,不一定非要? &分割,只要服务器能识别就行,长度也不是http协议限制的,一般是服务器或浏览器限制
TCP与HTTP对应关系
- 一个tcp连接可以建立多个http
- http/1.1 不能在一个tcp上同时运行多个http请求,也就是不必等待响应继续发送下一个请求(有个pipelining技术但是淘汰了)
- http/2 以上支持一个tcp同时发送多个http请求(multiplexing技术)
- 可能有的浏览器不支持http/2以上的协议,那就只能同时建立多个tcp连接实现并行传输了,chrome最大支持六个tcp连接
DNS负载均衡策略
一个域名可以对应多个ip地址
-
在很多用户同时访问一个ip地址时,服务器会不堪重负,dns服务器就通过一些策略把域名解析为不同的ip地址,这个可能以不同地理位置展示不同内容....
-
策略有:轮循,权重轮循,响应时间均衡策略等
SSL的工作流程
总结一句话就是:使用非对称加密传递密钥,使用这个密钥对通讯信息对称加密
- 客户端建立ssl连接请求(请求包含协议号、客户端支持的协议版本、一个随机数A)
- 服务端把数字证书(包含公钥X)发送给客户端验证(会把一个随机数B一起发送)
- 客户端验证通过
- 客户端使用这个公钥X加密预密钥C
- 服务端使用公钥X对应的私钥Y(非对称加密)解密C
- 双方来往的消息都使用(A B 两个随机数和预密钥 C 生成的会话公钥Z)加密解密
- 对称加密快,但是无法确保安全的传输密钥(传输密钥给对方用) 非对称加密更安全(你可以截获我的密钥 反正我不用他加密)但是慢
cookie
客户端通过浏览器向服务器请求时,会附带的一小段数据!!一般是上次通讯过程中服务器发送到浏览器并存储在本地的!!!
- 用途:客户端状态管理(刷新后保持登录状态、购物车添加),个性化配置(用户自定义主题等)、跟踪用户行为(浏览历史等)
- 分为临时性和持久性
session
客户端与服务器建立连接后服务器会生成一个会话(session ID),这个ID发送给客户端存储在浏览器,只要通过这个浏览器访问服务器就会携带这个id,服务器根据id检索会话内容,实现类似于cookie的功能,但他是存在服务器端的而且关闭浏览器/超时清空
-
事实上,大多数浏览器都是在cookie中存储session ID的,如果禁用了页面cookie,就会在url中以参数sid=xxx传输
-
区别:cookie只有ASCII字符串(session是object)可以存储,而且一般只有4k,还不安全,但不能都用session,服务器顶不住啊
SQL注入攻击
-
在http请求中注入恶意sql查询语句,比如注入一个 password : ‘ or ‘1’=’1 ,服务器接收到这个请求,解析到这个参数,就会把参数构建到数据库中,而这个语句永远为真,所以就实现了破译密码。。。。
-
防范措施:服务器和应用程序间加防火墙、用户输入验证和过滤、控制数据库权限、参数化传值(用%s传,而不是直接解析语句)
XSS攻击
-
用户输入的地方,利用html会把<> </>内的内容解析为代码,在里面嵌入恶意js代码,获取cookie等敏感信息
-
防范措施:前端对输入字符串做长度限制,大于小于号做转义、输入过滤
ARP与RARP
- ARP用于将ip地址解析为MAC网卡地址,因为一串ip地址上哪知道你的设备在哪?只有知道了硬件唯一标识才可以!!!
- RARP是逆向ARP,设备开机后没有自己的ip地址,要向RARP服务器发送自己的MAC地址,服务器才会给你分配一个ip地址!!!
常见的端口号
0--1023比较知名
- http 80 https 443
- ftp控制 20 ftp数据 21
DDos攻击
恶意控制大量网络设备,对某服务器发送大量请求导致占用网络资源。使得系统瘫痪
- 负载均衡、分布式系统,保证崩了一台还有其他的可以用
- DDos服务商,通过过滤异常流量预防攻击
MTU和MSS
- MTU是最大传输单元 ,硬件规定,如以太网是1500字节,不包含以太网帧头帧尾
- MSS是最大分段大小,决定了一个TCP包最大可以发送多少字节,一般1500-20(ipv4头)-20(tcp头)=1460
缓存过期机制
- 请求头或响应头包含Cache-Control标头

请求头包含说明我想要个可以缓存的资源,这个资源不要缓存太久的
响应头包含说明它的最长存储时间
- 注意:这个标头除了max-age,还有no-cache(不要直接使用缓存 重新获取最新资源)和no-store(不要存储缓存!)
- 包含Expires标头

TCP头部信息
- 16bit -- 源端口号(一般自动设置,比如http 80)
- 16bit -- 目标端口号 标识应用程序
- 32bit -- 序列号:初始被设为随机值ISN,之后每次这个值 = ISN + 已发的数据量
- 32bit -- 确认号:接收方收到的序号值 + 1
- 4bit -- 首部长,一般是5,表示首部一共5 * 4 = 20字节
- 6bit -- 保留位
- 6bit -- 标志位:URG ACK PSH RST SYN FIN
- 16bit -- 窗口值:确认收方的接受能力,用于流控
- 16bit -- 校验和
- 16bit -- 紧急指针
- 其他:选项(例如MSS) + 填充
TCP连接状态

- 注意:两边状态不是兼等的,TIME_WAIT指的是发完最后一个ACK之后的2MSL时间 CLOSE_WAIT指的是收到断联请求到发FIN(非ACK)
为什么是2MSL(msg segment lifetime TCP报文的最长存在时间)?
-
因为最后一包ACK可能会丢(以客户端主动断开为例)如果服务端超过MSL还没收到ACK就代表丢包了,就会重发FIN-ACK过去,重发的过程最大也要消耗MSL 所以对客户端来说超过2MSL没收到就表示可以正常断开!!!
-
SYN=1的报文不携带数据且消耗序号 ACK=1的报文只有携带数据才消耗序号,比如第三次握手不带数据(也可以带数据)就不会消耗
为什么不能只用两次握手?
- 因为第三次握手让服务器端确认客户端正常接收,比如第二次握手的SYN+ACK丢失 客户端没收到 但服务端默认收到了 于是分配资源造成浪费
RTO : 这次发送到超时后导致下次发送的时间; RTT : 正常发送到收到ack(一个来回)。 一般RTO用RTT计量,如2RTT 4RTT
应用层常见协议

补充 SNMP 161 udp
半连接队列
- 客户端发送SYN请求连接,服务端收到后进入SYN_RECV状态,这种状态下的请求会被放到半连接队列,三次握手完的请求是全连接
- 超时等待机制,指服务器发送SYN-ACK后一段时间后收不到客户端的ACK就会重发,这个重发时间一般是指数1 2 4 8 (超过最大次数就会把消息移除半连接队列)
- SYN攻击,就是客户端通过伪造的IP地址不断的向服务器发连接请求,导致正常的SYN连接请求无法及时处理
- SYN解决方案:缩短超时时间 增加半连接队列长度 手动看大量随机ip地址
四大拥塞算法
慢启动 拥塞避免

- 慢启动初始化拥塞窗口(发送方一次可以连续发几个包)为1,此后每收到一个ack就让窗口+1,所以第二次就成了2 并且受到俩ack,那么第三次就成了2+2=4 下次就是4+4=8....
- 到了24的时候,RTO(超时时间)没收到24个ack,说明可能(这里是可能!!!)丢包了,于是重新启动
- 注意!!本来的阈值16,RTO后就变成了24/2=12!!
快速重传
可以看到,24之后一下子落到1,而且要RTO的时间(很可能时偶然丢了某一个包,而不是拥塞)这也太浪费了,所以就提出了这个算法
- 3丢了,接收方在接收到4 5 6后一直重复的想要3(具体表现是发送确认2给发送方)发送方收到三次请求,忍不了了就重发3了

快速恢复
- 用于快速重传后的恢复,本来(通过RTO触发的慢启动)是24--1,现在(通过快速重传触发的)是16--8(这里也有8+3=11的)
为什么非要是三次? 实践证明的。。两次更有可能是丢包,四次就太久了
总结

socket编程
TCP UDP
//客户端
//创建socket,0表示根据第二个参数(TCP套接字)自动选择协议IPPROTO_TCP,udp用SOCK_DGRAM
int sock_c = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in info;
info.sin_family = AF_INET;
info.sin_port = htons(8080);
info.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock_c, (struct sockaddr*)info, sizeof(struct sockaddr));
// send 和 recv 的 0 表示默认,也可选,主要是是否阻塞发送、阻塞接受、是否启用紧急指针发送!
send(sock_c, "Hello world", strlen("Hello world"), 0);
char buff[1024] = {0};
recv(sock_c, buff, 1024, 0);
close(sock_c);
//服务端
int sock_s = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in info;
info.sin_family = AF_INET;
info.sin_port = htons(8080);
info.sin_addr.s_addr = INADDR_ANY;
bind(sock_s, (struct sockaddr*)info, sizeof(struct sockaddr));
listen(sock_s, 5); //5表示最大监听五个客户端
accept(sock_s, (struct sockaddr*)info, &sizeof(sockaddr_in));
recv(sock_s, buff, sizeof(buff), 0);
send(sock_s, "Hello", sizof("Hello"), 0);
close(sock_s);
如何保证TCP可靠连接?
- 三次握手四次挥手保证连接建立和断开是可信的
- 序列号、ack序号确保不会乱序,以正确顺序交给应用层
- 超时重传等机制确保可以完整的收到数据包
- 拥塞控制算法确保传输速率合适,不会发生太久的拥塞导致频繁丢包
- 首部的校验和确保可以收到正确的(未被篡改的)数据包(不能完全保证,可用md5在发端(加密后随数据发送)和收端比较结果)
TCP和UDP区别
- TCP面向连接,UDP无连接
- TCP保证可靠交付,传输结果无差错、不丢失、不重复、有序,udp尽最大努力尽快传输
- TCP面向字节流,也就是说没有明确边界,靠收方按序号重组,UDP面向报文,应用层交下来的加个首部直接发出去
- TCP首部开销20,UDP是8
- TCP点到点,UDP可以一对一多对多 多对一一对多(tcp需要bind,udp不需要,所以写多个套接字就能实现)
- TCP信道属于全双工可靠信道,UDP是不可靠信道
UDP在socket编程中,一般不要一次发太多,一方面是以太网的MTU(1500字节)限制 一方面是IP数据报长度限制,一般小于576-8-20,576是互联网规定的MTU,8是udp首部,20是ip数据报首部
ICMP
ping是基于它实现的,位于网络层,可以用socket编程实现
- 报文分为询问报文(回送请求 回送回答 时间戳请求和32位回复)、差错报告报文(终点不可达 超时 路由错误 参数错误)
IP协议和子网掩码
ip地址和子网掩码按位与 得到网络地址,ip地址和取反后的子网掩码按位与,得到主机地址!
- ipv4 地址一共32位,分四段,每段8位所以最大255,子网掩码指有几个1
- 比如192.168.2.3/24,这个24就是24个1的意思,已知32位所以剩下8个0 即255.255.255.0
- 网络号决定处于哪个子网,主机号取决在这个子网的哪里
TCP发送背后的故事
- IP协议报文头,包含源地址、目标地址、协议信息(上层用TCP就是06) MAC帧头包含源 目的 协议(0800 IP 0806 ARP)
- ARP是以广播方式工作的(在网络中大喊这个ip是谁的 等认领)并且会缓存,但一般只有几分钟
- 0101转换为电信号,靠的是网卡(先缓存再转),开头加分隔符,末尾加帧校验序列,用网线发送
- 交换机,把电信号转为数字信号,并通过缓存的MAC表找到对方的地址,如果没有就广播并缓存
- 出了交换机来到路由器,路由器有MAC和IP地址,交换机没有,路由器去掉MAC头后经过交换机继续转发,重新包装MAC头!!
linux收发数据包
- 网卡是一个硬件,专门负责收发网络包,
- 每次来都触发中断不合适,操作系统做法是用软中断ksoftrd线程,来了网络包,通过DMA写入环形缓存区,并触发一次硬中断,硬中断启动这个线程后续数据交给他处理!!!(NAPI机制)
- 发送,比如TCP,实际上是先把数据写入内核区sk_buff,然后发送副本,收到ACK后再删除数据,不同层的数据都从sk_buff缓存,添加首部的手段是移动sk_data指针!!
- 全发送完后,会触发一次硬中断,释放sk_buff内存和环形存储区
HTTP报文
- 请求报文包括请求行:方法 URL 协议版本(HTTP1.1); 消息头:字段名+字段值 消息体(GET无)
- 响应报文包括响应行:协议版本、状态码以及简述;消息头;消息体
HTTP的发展
- HTTP1.1/2都是用的TCP HTTP3改用UDP了
- HTTP1.1,缺点有:队头阻塞(响应太慢导致下一个请求一直等) 缺乏优先级控制 只能客户端请求
- HTTP2是基于HTTPS的,会压缩头部(多个相似的请求 用HPACK算法维护头部信息表) 二进制数据 服务和客户都可以请求
- HTTP2也会导致队头阻塞,因为基于TCP,需要组装,如果丢了一包HTTP会被迫阻塞在这等待重传
- HTTP3干脆采用UDP改进的QUIC协议,可以解决对头阻塞,也就是丢包了就放弃这段继续读下段

改进HTTP
- 改进HTTP1.1:减少请求次数(缓存,缓存过期机制 合并请求 减少重定向次数 302发给代理服务器这样) 对响应进行压缩,比如png压缩成WebP
- 改进HTTPS,充钱买更贵的CPU(节省加解密时间)、用更新版本的ssl、session会话、用ECDSA证书而非RSA,节约证书长度
- RPC是一种调用方式,性能好于1.1,因为不用考虑响应码啥的,一般用于微服务
- 比如扫码登陆,实际上是客户端没做任何事就收到了响应,是前端不断轮询后端看是否扫过了,轮询时间不能太短,所以就会卡顿。
- 解决方案是:一旦出现扫码立即发给服务器请求,并设置很长的超时时间,比如30s,30s后立即再发一次请求,表现在用户就是很快收到响应
- websocket就是基于TCP的协议,第一次肯定是http,请求里带

HTTP会返回101 这个码表示切换协议!

- websocket完美继承TCP的全双工,也就是收发可以同步进行,HTTP1.1就不行,响应了才能发
TCP保活机制
- Linux里

- 自己在应用层实现心跳
为什么非要三次握手?
- 两次握手,会造成重复建立连接(syn超时重传)有去无回,序列号不好更新
- 四次握手,SYN+ACK没必要分开发
- 第三次握手哪怕丢了也没关系,后面再发的数据可以当成第三次握手!!
- 第一次握手丢失了,会触发重传,重传的序列号等于刚刚的那个~ 详情往上翻那个算法
- 如果第二次握手丢失了,也就是客户端没收到ack就会继续重传,一般有最大重传次数,关闭连接
- SYN攻击指的是疯狂伪造ip发送SYN,服务器端第二次握手他就不回复你,占满半连接队列
常用linux命令
- netstat -napt查看tcp连接情况
- route -n查看路由表,用于客户端多张网卡确定路由的,把目标地址和子网掩码按位与得到结果,都不匹配就选默认路由0.0.0.0 跟的gateway表示下一路由器的地址,转发到这个路由器
- arp -a查询arp缓存

浙公网安备 33010602011771号