网络七层
应用层 http协议:用于如何封装数据
表示层
会话层
传输层 tcp/udp协议:传输控制协议 解决数据在网络中的传输
网络层 ip协议: 解决数据在网络中的传输
数据链路层
物理层
tcp三次握手
第一次握手: 客户端向服务端发送请求报文,并进入syn_send状态
第二次握手: 服务器收到请求报文,若同意连接,会发送一个应答,服务器进入syn_recv状态
第三次握手: 客户端收到服务器同意应答,向服务器发送一个确认报文,连接建立完成
为什么是三次不是两次?
若只是两次握手,客户端没有什么影响,仍然是获得服务端应答才开始传输数据
但是,服务端在接收到连接请求之后就进入传输状态,此时若是网络拥塞,客户端发送的连接请求迟迟不能到服务端,客户端便会超时重发,如果服务端收到这条消息,便建立连接,开始通信,结束后释放.但是如果此时失效的连接到达服务端,由于两次握手,服务端便会进入连接状态,等待发送数据或者主动发送数据,但此时客户端早已关闭,服务端会一直等下去,这样会浪费服务端资源
为什么不是四次?
三次握手是保证双方能够收发信息的最低值,无论多少次握手都不能确保信道的可靠,单通过三次可以至少确认信道可用,再往上加握手次数也只是加大信道可用的可信程度
tcp四次挥手
tcp的释放需要四步
前两次挥手用于断开一个方向的连接,后两次用于断开另一个方向
第一次挥手: 若A认为数据发送完成,他需要向B发送一个连接释放的请求
第二次挥手: B收到连接释放请求后,会通知响应程序,告诉它A向B这个方向的连接已经释放,此时B进入close_wait状态,并向A发送释放连接的应答 A收到该应答,进入fin_wait_2状态,等待B发送释放请求
第二次挥手完成后,A到B方向的连接已经释放,B不会再接收数据,A也不会再发送数据,但是B到A方向的连接仍然存在,B可以继续向A发送数据
第三次挥手: 当B向A发送完所有数据后,向A发送连接释放请求,B进入last_ack状态
第四次挥手: A收到释放请求后,向B发送确认应答,此时A进入time_wait状态,持续2sml,进入closed状态
为什么A要先进入time_wait状态,等待2msl再进入closed状态?
客户端最后一次向服务端回传ack时,有可能因为网络情况服务端收不到,服务端会再次发送fin包,此时若客户端已经关闭,则服务端无法收到ack包,无法关闭,因此客户端需要等待2msl
其中msl指的是数据包在网络中的生存时间,数据包在网络中有生存时间,超时未到达就会被丢弃 这个时间是1msl time_wait需要2msl才进入closed,若2msl没有收到fin,说明服务端已关闭
tcp与udp的区别
tcp面向连接 在发送数据之前需要建立连接(三次握手) udp是无连接的
tcp提供可靠,有序的服务,且按序到达 udp尽最大努力交付,但是不保证交付可靠
udp有较好的实时性,效率比tcp高 适用于高速传输和实时性有较高的通信或广播
每一条tcp都是点对点 udp可以一对多 多对多
tcp对系统资源要求较多,首部开销大 udp较少
tcp报文
源端口 目的端口 序号 确认序号 窗口:告知发送端接收端的缓存大小 数据
超时重传
在发送某一个数据之后开启一个计时器,在一定时间内没有获得ack报文,则重新发送,知道成功或者最大重发次数,重传超时时间RTO RTT连接往返的时间
滑动窗口
提供tcp的可靠性 提供TCP的流控特性
tcp的滑动窗口的可靠性是建立在确认重传的基础上的
发送端窗口只有在接收端返回ack确认后,才会移动滑动窗口的左边界
接收端可以根据自己的状况告知发送端窗口大小,控制发送端的收发,进行流量控制
拥塞控制
拥塞控制就是防止过多的数据注入到网络中 发送方会维持一个叫做拥塞窗口cwnd的状态变量,拥塞窗口大小取决于网络的拥塞程度 ,发送窗口小于等于拥塞窗口
拥塞控制是一个全局性过程 流量控制是点对点通信量的控制
TCP拥塞控制有四个核心算法:慢开始 拥塞避免 快重传 快恢复
拥塞窗口: 大小取决于网络的拥塞程度,动态的变化
慢开始
不要一开始就发送大量的数据,先探测一下网络的拥塞程度,从小到大逐渐增加拥塞窗口的大小
一次传输轮之后拥塞窗口就加倍,但是为了防止cwnd增长过大引起网络拥塞,会设置一个门限ssthresh
当cwnd<ssthresh时 使用慢开始
cwnd>ssthresh 拥塞控制
cwnd=ssthresh 随机
拥塞避免
使得拥塞窗口缓慢增长,每经过一个往返时间就把拥塞窗口+1,实现线性增长(而慢开始时指数增长)
无论是慢开始阶段还是拥塞避免阶段,只要发现网络出现拥塞现象,(没有收到确认包),就把慢开始门限ssthresh设为出现拥塞时发送窗口的一半,然后把拥塞窗口设为1,执行慢开始
快重传
接收方在接收到一个失序的报文段之后立刻发送重复确认,而不是等待自己返回数据时捎带确认
发送方只要连续收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必等待设置的重传计时器时间到来
即发送方发送m1,m2,发送m3时丢失, 接收方回复三次重复请求,发送方继续发送m3
快恢复
1.当发送方连续接受三个重复确认时,执行乘法减小算法,把ssthresh减半,接下来不执行慢开始
2.考虑到如果是网络拥塞就不会出现好几个重传回复,所以发送方认为没有出现拥塞,此时不执行慢开始,而是把cwnd设为ssthresh的大小,然后执行避免拥塞算法
常见的端口
20 21 ftp
22 ssh
23 telnet
25 smtp 简单邮件传输协议
80 http
ssh与telnet
ssh与telnet都是基于tcp/ip的可以远程登录另一台主机的协议
不同点在于:
ssh 端口号 22 telnet是23
ssh加密传输 telnet是明文传输
ssh使用公钥对访问服务器的用户进行身份验证,telnet没有
socket
标识网络进程 ip+协议+端口
网络中的进程通过socket来通信
socket是个接口而不是协议 它是对tcp/ip的封装
socket连接: 一对套接字 clientSocket serverSocket
- socket(int domain,int type,int protocol)创建一个socket domain 协议域 type socket类型 protocol 协议
- bind() 分配地址 通常服务器在启动时候会绑定一个地址(ip地址+端口号),用于提供服务,客户可以通过它来连接服务器 而客户端就不用指定,有系统自动分配一个端口号与自己ip地址组合. 所以服务端在listen之前会调用bind,而客户端不会,是在connect时由系统随机生成一个
- listen() 监听 作为一个服务器,在调用socket,bind之后会调用listen来监听这个socket,如果这时客户端调用connect发出连接请求,服务端会接收
- connect()
- accept() tcp服务器依次调用socket,bind,listen之后,就会监听指定的socket地址了.tcp客户端依次调用socket,connect之后就向tcp服务端发送一个连接请求. tcp服务端监听到请求后,会调用accept来接收该请求,这样连接就建立好了,可以开始网络IO操作
- 如何检测socket是否断开
心跳包 - 发送时顺序接受时顺序乱了,原因?
经过的路由不同 - http协议只是tcp协议的应用层,tcp的难点在于服务端
建立socket连接需要一对套接字,一个位于客户端ClientSocket,一个位于服务端ServerSocket,套接字之间的连接分为三个部分:服务器监听,客户端请求,连接确认
socket是长连接,http是短连接
若双方是socket连接,可由服务器向客户端发送数据
若双方是http连接,由客户端发送请求后,服务端将数据回传给客户端
socket三次握手
当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
socket流程
服务器:
1.创建一个socket
2.bind一个句柄(端口和地址)
3.listen设置监听的客户数
4.accept客户端的句柄
5.读写。
客户机:
1.创建一个socket
2.connect到服务器
3.读写操作。
五元组
协议 端口号 IP 端口号 IP
tcp的状态
Listening 侦听远方的tcp端口连接请求
syn_sent 客户端,syn_sent状态
syn_received 服务端
established 打开的链接
fin-wait-1 主动关闭端调用close(),其tcp发出fin主动关闭连接,进入fin-wait-1
fin-wait-2 主动关闭段接到ack后,进入fin-wait-2
close-wait 被动关闭端接收到fin后,发出ack回应,进入close-wait
last-ack 被动关闭端一段时间后,发送一个fin,等待对方ack
time-wait 主动关闭端接到fin后,发送ack,进入time-wait
closed 被动关闭端接受ack后
TCP的Q
syn队列 accept队列
syn队列 保存处于SYN_SENT与SYN_RECV状态的请求
accept队列 保存处于established状态的请求,但是应用层没有调用的请求
syn到达->插入syn队列->返回syn+ack->由syn队列取出->插入accept队列
第一次握手 当客户端syn到达时,若syn队列未满,插入 满了则丢弃
第二次握手 服务器返回syn+ack 表示收到
第三次握手 客户端发起ack,表示客户端已经准备完毕,此时服务器将连接从syn队列移至accept队列,三次握手完成
若是服务进程处理的很慢,导致大量的请求放到accept队列,会将accept队列阻塞,当accept队列满了之后,即使client传来ack,服务器也不会响应 此时,server通过tcp_abort_on_overflow来决定返回值,0表示丢弃,1表示发送RST通知给client,client显示read timeout或者connect reset by peer