侧边栏壁纸
  • 累计撰写 247 篇文章
  • 累计创建 16 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

套接字底层原理

kaixindeken
2021-04-20 / 0 评论 / 0 点赞 / 105 阅读 / 1,491 字

套接字简介

位于应用层的应用程序在基于 TCP 协议或 UDP 协议进行通信时,需要用到操作系统提供的类库,这种类库一般称为 API(Application Programming Interface,应用编程接口)。

使用 TCP 或 UDP 时,又会广泛使用到 Socket(套接字)API,Socket 原本是由 BSD UNIX 开发的,但是后来被移植到 Windows 的 Winsock 以及嵌入式系统中。应用程序利用 Socket,可以设置对端的 IP 地址、端口号,并实现数据的接收和发送:

1.png

下面我们分别以 TCP 和 UDP 为例,详细介绍 Socket 的底层原理和相关 API 函数。我们先从较为复杂的 TCP 开始。

TCP 套接字

TCP 的服务端要先监听一个端口,一般是先调用 bind 函数,给这个 Socket 赋予一个 IP 地址和端口。

当服务端有了 IP 和端口号,就可以调用 listen 函数进行监听。在 TCP 的状态图里面,有一个 listen 状态,当调用这个函数之后,服务端就进入了这个状态,这个时候客户端就可以发起连接了。

在操作系统内核中,为每个 Socket 维护两个队列。一个是已经建立了连接的队列,这时候连接三次握手已经完毕,处于 established 状态;一个是还没有完全建立连接的队列,这个时候三次握手还没完成,处于 syn_rcv 的状态。

接下来,服务端调用 accept 函数,拿出一个已经完成的连接进行处理。如果还没有完成,就要等着。

在服务端等待的时候,客户端可以通过 connect 函数发起连接。先在参数中指明要连接的 IP 地址和端口号,然后开始发起三次握手,操作系统会给客户端分配一个临时的端口。一旦握手成功,服务端的 accept 就会返回另一个 Socket 用于传输数据。

这里需要注意的是,负责监听的 Socket 和真正用来传数据的 Socket 是两个,一个叫作监听 Socket,一个叫作已连接 Socket。

连接建立成功之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。

下面这个图就是基于 TCP 协议的 Socket API 函数调用过程:

1.png

说 TCP 的 Socket 就是一个文件流,是非常准确的。因为,Socket 在 Linux 中就是以文件的形式存在的。除此之外,还存在文件描述符。写入和读出,也是通过文件描述符。

UDP 套接字

基于 UDP 的 Socket 编程要简单一些,因为 UDP 通信无需建立连接,所以不需要三次握手,也就不需要调用 listen 和 connect 函数,但是,UDP 的的交互仍然需要 IP 和端口号,因而也需要 bind。UDP 是没有维护连接状态的,因而不需要每对连接建立一组 Socket,而是只要有一个 Socket,就能够和多个客户端通信。也正是因为没有连接状态,每次通信的时候,调用 sendto 和 recvfrom,都可以传入 IP 地址和端口。

0

评论区