TCP三次握手与四次挥手

常见的Posix API

server: 1.socket();2.bind();3.listen();4.accept();5.recv();6.send();7.close();
client: 1.socket();2.bind(optional);3.connect();4.send();5.recv();6.close();

在服务端各个API的作用:

socket() 是文件系统分配的一个fd,并且置为tcb;bind()是为tcb绑定本地的ip和port;listen()是把tcb置为一个listen的状态;accpet()是从全连接队列取出一个节点分配一个fd;recv()就是从对应的fd拷贝出recvbuffer;send()是把数据拷贝进sendbuffer中;close()是把fin包放到sendbuffer中,兵器把fd回收。剩下的和跟应用程序没关系了

在客户端各个API的作用:

客户端中,如果bind()调用就会是一个固定的port,不调用就是一个随机端口;cennect()作用就是准备一个syn包交给协议栈,协议栈把它发送出去,等待三次握手完成之后connect再返回;其他的API和服务器差不多。

三次握手过程

三次握手
问题1 三次握手,分别发生在服务器和客户端那个函数里?

服务器:listen()和accpet();
客户端:connect();

三次握手过程:

客户端先发起第一个包,syn包seqnumber = 12345,此时将包入半连接队列,并返回给客户端syn和ask包(此时seqnumber = 12346,指的是12345之前都收到了),之后客户端回一个ack包,服务器收到ack包去半连接队列查询,查到,则对半连接队列move,并插入全连接队列,此时accept()来全连接队列取走fd。

问题2 accpet怎么知道全连接队列有节点呢?

accpet有两种,1 阻塞 2 非阻塞
若是阻塞,则accpet一直等着全连接队列,有数节点取出;若是非阻塞 ,如果全连接队列为空直接返回-1,不去等待,当第三次握手加入节点会有一个信号发出来的。

tcp转态迁移图:
server视角(虚线箭头所指):
serverclient视角(实现箭头client视角(实线箭头所指):
client

数据传输过程

问题3 为什么会出现粘包拆包问题,如何解决?

tcp会有粘包问题(udp无),tcp是基于字节流发送的(应用程序看到的数据是一个整体),粘包是由于发送端发送的次数比接收端接收的次数多,一般有以下几种情况会发生粘包:发送端将多次写入缓冲区的数据一次发送;接收端没有及时读取接收缓冲区的数据;发送的数据大于TCP发送缓冲区剩余空间大小会进行拆包。

websocket协议应对方式是在应用层协议为每一个包加上分隔符,buffer[idx] = ‘\r\n\r\n’
tcp解决方式:1 在协议头加上要传输的数据长度;2 加上包的分隔符。

四次挥手过程

断开连接不分服务器客户端,只分主动和被动。
Client将FIN置为1,序号seq=M,发送给Server,进入FIN_WAIT_1状态
Server收到后,将ACK置为1,ack=M+1,响应给Client,进入CLOSE_WAIT状态
Client收到响应后,进入FIN_WAIT_2状态
Server在结束所有数据传输后,将Fin置为1,seq=N+1,发送给Client,进入
LAST_ACK状态
Client收到后,将ACK置为1,ack=N+1,响应给Server,进入TIME_WAIT状态,等待
2MSL后,进入CLOSED状态
Server收到后,进入CLOSED状态

四次挥手问题4 出现大量close_wait()的原因,如何解决?

原因:没有及时调用close()函数;业务逻辑有问题
解决方案:提前调用close();将业务逻辑放到线程池处理,close放到另一个线程中处理、

问题5 出现time_wait怎么做?

应用中产生大量TIME_WAIT状态的根本原因是频繁创建断开连接TCP连接。要解决TIME_WATIT状态过多的问题,就要分析我们的应用把频繁创建的短连接改为长连接。
后台业务服务器,通常需要调用redis、mysql以及其他http服务和grpc服务,在服务相互调用中,如果使用的是短连接,高并发时就会产生大量TIME_WAIT。一般情况下,redis等客户端会有连接池,我们要做的是设置好相关的连接服用参数,一般会有连接数、连接重用时间、连接空闲数等。所以在应用中通过设置合理的连接池参数可以避免TIME_WAIT状态过多的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值