我们先来说说UDP
UDP的特点
UDP传输的过程类似于寄信.
无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
面向数据报: 不能够灵活的控制读写数据的次数和数量
UDP的缓冲区
UDP没有真正意义上的 发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作;
UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;
TCP协议
1.确认应答机制
TCP将每个字节的数据都进行了编号. 即为序列号
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发.
2.超时重传机制
主机A发送数据给B后,可能因为网络堵塞等原因,数据无法到达主机B
如果主机A在一个特定时间间隔没有收到B发来的确认应答,就会进行重发
但是,主机A未收到B发来的确认机制,也可能是因为ACK丢失了
因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉.
这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果.
那么, 如果超时的时间如何确定?
最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返回”.
但是这个时间的长短, 随着网络环境的不同, 是有差异的.
如果超时时间设的太长, 会影响整体的重传效率;
如果超时时间设的太短, 有可能会频繁发送重复的包;
TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间.
Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时
间都是500ms的整数倍.
如果重发一次之后, 仍然得不到应答, 等待 2500ms 后再进行重传.
如果仍然得不到应答, 等待 4500ms 进行重传. 依次类推, 以指数形式递增.
累计到一定的重传次数, TCP认为网络或者对端主机出现异常,强制关闭连接
3.连接管理机制
三次握手
第一次握手:首先PC1向PC2发送建立连接请求,发送SYN报文,所以自己的SYN同步序号位置为1,SYN=1,同时还需要带上自己的随机序列号x,以便验证自己的身份,所以Seq=x。
第二次握手:PC2接收到PC1的请求,向PC1进行回复,它要回复的内容是SYN和ACK报文,首先ACK=1,是因为PC2确定收到建立连接请求,Ack=x+1,这里是确定对PC1 x序列号的确定,确定我是收到的PC1的连接请求,还有同步位SYN置为1,SYN=1,同时PC2也要带上自己的随机序列号y,以便证明自己的身份。
第三次握手:PC1收到消息,再次回复的时候就只发送ACK确认报文就可以了,PC1收到消息,ACK确认位置为1,ACK=1,确认收到的是PC2对自己的回复,Ack=y+1,同时PC1自己的随机序列号x要更新成x+1,本来自己的序列号是x,但是它已经被PC2确认接收过自己的第一次发送建立连接请求,所以变成Seq=x+1。至此,三次握手完****成,TCP完成建立连接**
四次挥手**
第一次挥手:首先PC1向PC2发送断开请求,FIN断开位=1,发送完事PC1立马进入fin_wait_1 第一次半关闭状态。
第二次挥手:PC2向PC1进行回复,ACK确定位置为1,ACK=1,发送确定完自身进入close_wait关闭等待状态。PC1收到后就等待PC2向自己发起断开请求了,自己进入第二次半关闭状态。
第三次挥手:PC2向PC1发起断开请求,发送FIN=1,自己进入last_ack,最后确认半关闭状态。
第四次挥手:PC1收到消息后进行回复,ACK确认位=1,发送完自身进入time_wait等待,此时不论对方有没有接收到确认信息,自身都会等待4分钟才能断开,而PC2假如立即收到确认消息,会立马断开,如果没有收到消息,会继续接收,直到接收到PC1的确认消息或4分钟后跟PC1一块自动断开。