目录
应用层
write,read这种接口只是单纯负责用户缓冲区与内核缓冲区之间的拷贝,tcp(传输控制协议)才是真正控制网络收发的。
用户之间需要协议定制
序列化与反序列化
网络计算器(代码)
序列化与分隔符
数据之间增加分隔符方便后续解析
报文与报文之间也需要分隔符方便对方识别一个报文的终点
另一种方案,报文前面加对应长度
守护进程接口
第一个参数为0就是把工作目录变为根,否则不变。
第二个参数为0就是把输入输出重定向到/dev/null(垃圾桶)。
http
url
URL 的全称是 Uniform Resource Locator(统一资源定位符)。
域名标识互联网中唯一一台主机,协议以及默认端口号表示该主机的唯一服务,资源路径表示位置。
问号后面是提交的数据,kv结构等号分开,多个kv之间用&隔开。
编码,解码
http请求与响应
用telnet查看响应,构建请求
响应回复
用fiddler工具进行抓包
抓包原理,请求和响应都要经过工具
用postman工具构建请求查看响应
httpserver项目(代码)
网络读取可以选择read或recv,flags是读取的方式
send前三个参数和write一模一样
代码
net_basic2_lesson/httpserver/my_httpserver · lyh/linux - 码云 - 开源中国
代码介绍
项目逻辑
http方法
数据通过表单提交
get方法时,参数通过url提交
问号分隔程序和参数,程序可以用子进程程序替换
post方法通过正文提交参数
http状态码
http报头
302重定向搭配location使用
浏览器发起请求,服务器提供不了服务但会告诉浏览器你应该找谁,浏览器听到后重新去找人
短连接:一次连接一个请求一个响应然后关闭连接
长连接:一次连接多个请求多个响应然后关闭连接
表示支持并选择使用长连接
content-type告诉服务器请求资源的类型
set-cookie的内容会保存在浏览器的cookie文件中
cookie存在的两个问题
1. 私人信息泄露
解决方法:浏览器登录时,服务器会生成session文件存放私人信息,返回对应的session id给cookie,把浏览器要维护的私人信息放在服务端去维护
2. cookie被盗取的问题
这个问题避免不了
https
https = http + ssl加密解密层
中间人攻击
加密方式
对称加密
非对称加密
https工作过程
方案1:只使用对称加密,不可行,密钥不安全会被拦截
方案2:只使用非对称加密,客户端到服务器是安全的,但服务器回复响应不安全,因为服务器只能用私钥加密,但公钥可以解密且公开的
方案3:双方都是用非对称加密
方案4:使用非对称加密和对称加密,一开始的非对称是为了把对称密钥安全给对方,后面对称是为了效率
方案2,3,4的安全问题
如果中间人在第一次通信就进行了拦截,把服务端给客户端的公钥替换成自己的公钥,这样非对称加密就不安全了
本质问题
解决办法:引入证书
方案5:使用非对称加密和对称加密和证书,基本和方案4一致,不同的是利用证书保证第一次服务端给客户端公钥的安全
证书
ca认证
证书包含签名和明文数据
证书申请流程
之前的方案4是服务端把公钥发给客户端,现在改进成服务端把证书发给客户端,证书里面包含公钥,如何保证证书的安全?
解决方法:数据签名
证书包含数据和签名
数据:明文数据
签名:将数据进行运算获得摘要,把摘要用CA私钥加密获得签名
对方验证证书的安全:将明文数据用算法获得摘要,将签名用CA公钥解密获得摘要(客户端会内置CA公钥),对比摘要是否相等。
这里有两个防守关卡,第一,客户是用CA公钥解密的,所以你只能用CA私钥加密,第二,判断摘要相等。
传输层
端口号
我一个浏览器可以同时打开两个百度网页,对方服务器怎么区分我?
答:用五元组标识一个通信,ip标识双方主机,端口号标识双方主机里的“人”,协议号标识我们用什么协议
端口号范围划分
知名端口号
答:一个进程可以有多个服务,一个用来传输,一个用来控制,反之一个服务不能在多个进程里
netstat
iostat
pidof
udp
报头
定长报头八字节,双方约定好除去八字节后面就是有效载荷
目的端口号告诉我交给谁
操作系统内部存在着大量报文要管理,先描述再组织,给每一个报文配备一个描述结构和缓冲区,这个结构标识缓冲区的位置各项信息,所谓的封装报文就是把报头结构体写入缓冲区,再把有效载荷写入缓冲区,最后管理这个缓冲区。
特性
面向数据报
缓冲区
tcp
read, write, recv, send是把用户级缓冲区拷贝到内核级缓冲区
tcp是把系统的发送缓冲区拷贝到另一个系统的接收缓冲区
协议段格式
首部长度包含报头和选项
窗口大小是指自己的接收缓冲区的剩余空间的大小。
发送方给接收方发报文时需要进行流量控制,也就是接收方的接收能力是有限的,发送方必须得知道并且减慢发送速度甚至停止发送。
序号与确认序号
序号是发送的数据块的最后一个字符的下标
发送缓冲区就是一个数组,一大串内容可能要分成几个报文发送,但一次发送多个报文,报文未必会按顺序到达,会造成乱序问题,所以序号可以让接收方知道报文的顺序
确认序号
6个标记位
作用是告诉接收方此报文的类型,因为tcp有三种交流场景,分别是建立连接,正常通信,断开连接,这三种场景双方交流都需要报文且报文的类型不同
ack: 判断确认序号是否有效,一般应答就需要看确认信号,所以它代表的是确认类型的报文
syn: 表示这个报文是要建立连接的,是要和我三次握手的
fin: 表示告诉对方我要断开连接了
psh: 告诉对方赶紧把接收缓冲区的数据读走,有这么一种情况,对方的接收缓冲区满了,我方的发送缓冲区也满了,因为发不出去一直堆积着,造成了写阻塞,此时我方就会发送一个psh报文告诉对方赶紧把数据读走
rst: 要求重新建立连接,因为有可能会建立失败,如下图客户端三次握手中,第三次发出应答之后,客户端就认为连接成功了,但是客户端并不知道发出的应答对方会不会收到,假如服务端没收到ack, 这时客户端继续往下走发送数据通信,然后服务端收到数据后很诧异,我们明明还没建立连接怎么就通信了,所以服务端就会发送rst让对方重新连接
urg: 表示紧急指针有效
紧急指针:表示紧急数据在数据中的偏移量,紧急数据默认只能一个字节,紧急数据会被优先处理
确认应答机制
发送方发送一个报文,里面的序号会填此次数据块的最后一个字节的编号,接收方收到后返回一个应答报文,在确认序号中填写对方发送的最后一个字节的编号加1
超时重传机制
有两种情况,发出去的报文丢了或者对方的应答我没收到,这时当我超过特定时间没收到应答时,我就会重新发送数据。
第二种情况可能会造成对方接收数据重复了,这个问题可以被序号解决。
特定时间如何规定?
连接管理机制
connect()就是发出了syn报文然后就阻塞了,直到接收到对方应答和syn,然后我方发出应答,connect就返回了。
accept并不参与三次握手,它只会把建立好的连接拿上来,如果没有就阻塞。
三次握手中,双方的连接状态变化
为什么要三次握手?
1. 验证全双工,双方检查自己的收发通路是否通畅,必须发一下,然后收一下
2. 服务端建立连接是需要成本的,所以最好先让客户端建立连接,然后服务端再建立连接,保证连接不被浪费
为什么握手会捎带应答而挥手不会?
因为客户端请求握手,服务端是必须答应的,所以就肯定服务端会应答和请求,而挥手,客户端要断开连接但服务端未必想断开连接,可能服务端还有数据要发。
当对方发送关闭连接时,我方还可以继续发送数据,因为此时是半关闭状态,所以为什么不捎带应答,因为对方想关闭我未必想关闭。
listen的第二个参数
当服务端建立好连接后,如果上层没有拿取这个连接,那么系统需要临时管理这个连接,当有多个这些连接时,系统会用队列管理这些临时连接,如果上层accept了,就从这个队列拿连接,这个队列叫全连接队列,listen第二个参数+1就是这个队列的最大长度。
如果全连接队列满了,客户端再发起连接请求时,客户端可以进入连接成功的状态,但是服务端只会停留在syn_recv状态,这种状态叫半连接,系统也会用半连接队列维护,但是会定期释放。
四次挥手中的time_wait状态
如果服务端主动断开连接,那么它短时间内无法重新绑定,因为服务端会进入time_wait状态,此时连接没有彻底断开,ip和端口还在被之前的进程使用,所以新的进程无法绑定。下面这个接口可以让time_wait状态的服务器立刻重新启动。
第一个参数是套接字,第二个参数是socket层级,第三个参数是地址复用和端口复用,第四个参数是1(true)。
为什么time_wait状态会持续若干时间?
1. 然后双方在路上的报文被收到,避免残留在网络中
2. 保证最后两次挥手的成功率,万一最后一个ack丢失了还可以重发
流量控制
接收缓冲区满了之后需要等待数据被读走,这时双方都有策略,发送方:等待一段时间后会发送窗口探测报文,获取对方回应从而知道对方窗口大小。接收方:数据读走后会发送窗口更新报文给对方。
滑动窗口
发送方发送数据但未收到应答时,会等待一段时间重新发送,所以发送的数据会在发送缓冲区保留一段时间。
发送缓冲区的区域划分
关于丢包与滑动窗口的问题,有两种情况,丢应答包或丢数据包
丢应答包
应答虽然丢了但是数据是实实在在接收了,所以后续报文的确认序号可以让我们知道数据收到哪里了,假如丢了2001的应答,但是接收到了5001的应答,我们就知道数据已经接收到5000了,可以直接把窗口移动到5001
丢数据包
确认序号永远只会标记已经接收的数据,如果接收了1000和3000,丢了2000,那么确认序号永远是1001,当收到三次同样确认序号的应答时,就会重新发送数据
为什么有了快重传还要超时重传?
因为快重传有条件限制,需要收满三个同样确认序号的应答,假如无法满足条件呢,超时重传就是兜底的作用
延迟应答
发送方一次发送更多的数据则效率越高(因为IO),如何发送更多的数据取决于对方窗口大小,延迟应答可以给上层一点时间读走数据从而增大窗口大小。
拥塞控制
出现大量丢包可能是网络的问题
如何判断出现大量丢包的?答:滑动窗口内大量数据超时了
大量丢包怎么办?
解决方法:慢启动与拥塞窗口
一开始先发一个,然后两个,四个,八个
拥塞窗口增长阈值
阈值的定义:如图,第一次慢启动有初始阈值,当达到拥塞时,此时窗口是24,那么下次阈值就是前一次的拥塞点的一半也就是12,下一次慢启动也是从1开始
tcp异常情况
进程终止:连接会正常断开
机器重启:先关闭所有进程->进程终止
主机断电/网线断开:客户端直接消失,服务端不知道客户端的情况,会发送rst请求重新连接