TCP协议通信流程
一个服务器有可能有多个客户端来进行链接,链接一旦多了起来,同样需要对其进行管理。管理是需要成本的,体现在时间和空间上,即服务器和客户端为了维护这个链接、在系统层面都要提供一批数据结构来管理这批链接(udp不需要做、因此速度相对更快)。
CS模型:客户端主动发起链接、服务器被动,不会主动发起链接就叫做CS模型。 BS模型:通过游览器去访问服务器、本质上也是CS模型。
服务器初始化:
- 调用socket, 创建文件描述符。
- 调用bind, 将当前的文件描述符和ip/port绑定在一起; 如果这个端口已经被其他进程占用了, 就会bind失败。
- 调用listen, 声明当前这个文件描述符作为一个服务器的文件描述符, 为后面的accept做好准备。
- 调用accecpt, 并阻塞, 等待客户端连接过来符。
建立连接的过程:
- 调用socket, 创建文件描述符。
- 调用connect, 向服务器发起连接请求。
- connect会发出SYN段并阻塞等待服务器应答; (第一次)。
- 服务器收到客户端的SYN, 会应答一个SYN-ACK段表示"同意建立连接"; (第二次)。
- 客户端收到SYN-ACK后会从connect()返回, 同时应答一个ACK段; (第三次)。
这个建立连接的过程, 通常称为 三次握手。
数据传输的过程:
- 建立连接后,TCP协议提供全双工的通信服务; 所谓全双工的意思是, 在同一条连接中, 同一时刻, 通信双方可以同时写数据; 相对的概念叫做半双工, 同一条连接在同一时刻, 只能由一方来写数据。
- 服务器从accept()返回后立刻调用read(), 读socket就像读管道一样, 如果没有数据到达就阻塞等待。
- 这时客户端调用write()发送请求给服务器, 服务器收到后从read()返回,对客户端的请求进行处理, 在此期间客户端调用read()阻塞等待服务器的应答。
- 服务器调用write()将处理结果发回给客户端, 再次调用read()阻塞等待下一条请求。
- 客户端收到后从read()返回, 发送下一条请求,如此循环下去。
断开连接的过程:
- 如果客户端没有更多的请求了, 就调用close()关闭连接, 客户端会向服务器发送FIN段(第一次)。
- 此时服务器收到FIN后, 会回应一个ACK, 同时read会返回0 (第二次)。
- read返回之后, 服务器就知道客户端关闭了连接, 也调用close关闭连接, 这个时候服务器会向客户端发送一个FIN; (第三次)。
- 客户端收到FIN, 再返回一个ACK给服务器; (第四次)。
这个断开连接的过程, 通常称为 四次挥手。
TCP和UDP的对比
- TCP:
可靠传输、有连接、面向字节流
- TCP提供可靠的传输(有序,无差错,不丢失,不重复)
- TCP提供拥塞控制和流量控制机制
- TCP提供面向连接的传输,通信前要先建立连接(三次握手机制)
- TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组
- 每条TCP连接只能有两个端点(一对一)
- UDP:
不可靠传输、无连接、面向数据报
- 不可靠传输:将数据报文传递给下一层即可、其中发生了什么数据是否安全到达等等。UDP协议不再关心因此容易导致丢包。
- UDP不提供拥塞控制和流量控制机制
- UDP是面向数据报的传输,没有分组开销。数据报:读取数据是由明显边界的,要么读,要么不读,就好比去拿快递,要么拿一个,要么不拿,没有拿半个快递的说法。
- UDP支持一对一,一对多,多对一和多对多的交互通信。
- UDP存在的价值:1.简单2.不用创建连接3.越简单的东西,相对就较快
比如:允许丢包的场景:直播(卡了不会重播、效率高、简单、快速)
如何理解套接字文件描述符
套接字是一个抽象出来的概念,本质上也是一个文件描述符。
|