使用socket创建了fd(最开始创建fd时,fd为3。0、1、2分别被stdin stdout stderr占用)和tcb(tcp control block)。**一个TCB数据块包含了数据发送双方对应的socket信息以及拥有装载数据的缓冲区**。在两个设备要建立连接发送数据之前,**双方都必须要做一些准备工作,分配内存建立起TCB数据块就是连接建立前必须要做的准备工作。**fd 使用户层,tcp是内核层。socket 实现fd 和tcp 关联。五元组是tcp 的唯一标识。其中五元组包括(remote ip,remote port,local ip,local port,协议类型)通常使用5元组来标识一个数据包属于哪个会话,在数据包查重和流量对比时会使用较多,在网络分析领域也经常会涉及到。
# 二、 三次握手
发生在协议栈和协议栈之间
![三次握手](https://img-blog.csdnimg.cn/30f0b6feb53c40139040e52a3646fce0.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/9f2faa81409e424496910dd0928acc9d.png)
由上图可以看出:
**三次握手发生在**Connect执行连接,客户端给服务器发送syn,
服务器此时形成了tcb(有生命周期),确定5元组,加入到半连接队列(syn队列)
**半连接、全连接建立的前提:服务端必须进入listen状态**
服务端listen()之后实现第一次握手,listen()将listenfd置为listen的状态,可以进行三次握手
![在这里插入图片描述](https://img-blog.csdnimg.cn/126bd0cf26de4d5bbb273a1629b8a45e.png)
第三次握手之后,服务端运行函数accept()
三次握手成功之后调用accept函数(accept函数做两件事:1从全连接队列里取出一个结点;2为这个结点分配一个fd;为tcb和客户端连接做到一个一一对应的关系)
阻塞connect到客户端给服务器发送确认请求
非阻塞Connect不等直接返回
客户端fd tcb在创建socket时就创建好了
Fcntl设置阻塞(属性)是文件系统fd的属性,和三次握手没啥关系
如下图红点标记就是阻塞connect返回的时间结点
![在这里插入图片描述](https://img-blog.csdnimg.cn/8bb367523f00437cb999354bc2f9d55f.png)
**数据的发送**
Send:把用户数据拷贝到内核协议栈里面,tcb控制块里面(只调用一个拷贝过程)
再把内核协议栈数据发送给服务端,这是两个流程无关系
Recv:相反
![在这里插入图片描述](https://img-blog.csdnimg.cn/60e50a38a8f1456a8131c4524eb726aa.png)
Send返回-1:可能是内核协议栈sendbuffer满了
Recvbuffer满了,会给对端协议栈返回一个消息,告诉自己的内存空间是多少,还可以接受多少数据
Push标志位置1,立即推给业务程序
**粘包和分包**
可能情况 Send三次,内核协议栈发两次,recv两次(合包)
方法:在协议包头加上数据长度;或为每个包加个分隔符
![在这里插入图片描述](https://img-blog.csdnimg.cn/aac93360b1d146f38858546cf2d9cbe6.png)
**粘包的分析:**
1.正常情况:发送及时每消息发送,接收也不繁忙,及时处理掉消息。
![在这里插入图片描述](https://img-blog.csdnimg.cn/6d048ea5dd1147e7b871ea2ca78f19d0.png)
2.发送粘包,**多次间隔较小且数据量小的数据,合并成一个大的数据块**,然后进行封包. 这种情况和客户端处理繁忙,接收缓存区积压,用户一次从接收缓存区多个数据包的接