socket 编程

网络通讯的本质目标就是进程间通信

socket 编程模型

unix 系统 socket 是一种特殊的文件,双向管道,一端是应用,一端是缓存区

socket 连接应用和协议。应用程序 传输数据,就创建一个 socket 。向 socket 中写数据相当于将数据发送给另一个应用。应用从 socket 中读取数据,相当于接收另一个程序发送的数据。

在服务端有两种 Socket 文件,每个客户端接入之后会形成一个客户端的 Socket 文件,客户端 Socket 文件的文件描述符会存入服务端 Socket 文件。通过这种方式,一个线程可以通过读取服务端 Socket 文件中的内容拿到所有的客户端 Socket。这样一个线程就可以负责响应所有客户端的 I/O,这个技术称为 I/O 多路复用。

主动式的 I/O 多路复用,对负责 I/O 的线程压力过大,因此通常会设计一个高效的中间数据结构作为 I/O 事件的观察者,线程通过订阅 I/O 事件被动响应,这就是响应式模型。在 Socket 编程中,最适合提供这种中间数据结构的就是操作系统的内核,事实上 epoll 模型也是在操作系统的内核中提供了红黑树结构。

I/O 复用手段 同步调用

  1. select poll 线性结构,阻塞模型
  2. epoll 红黑树,非阻塞模型

每次 select 操作会阻塞当前线程,在阻塞期间所有操作系统产生的每个消息,都会通过遍历的手段查看是否在 3 个集合当中 (用户传入)

poll : 用户不需要用 select 来设置自己的集合,而是可以通过系统的 API 直接拿到对应的消息,从而处理对应的文件描述符,性能角度分析差距不大。

epoll 将进程关注的文件描述符存入一棵二叉搜索树,通常是红黑树的实现。在这棵红黑树当中,KeySocket 的编号,值是这个 Socket 关注的消息。因此,当内核发生了一个事件:比如 Socket 编号 1000 可以读取。这个时候,可以马上从红黑树中找到进程是否关注这个事件。

另外当有关注的事件发生时,epoll 会先放到一个队列当中。当用户调用 epoll_wait 时候,就会从队列中返回一个消息。epoll 函数本身是一个构造函数,只用来创建红黑树和队列结构。epoll_wait 调用后,如果队列中没有消息,也可以马上返回。因此 epoll 是一个非阻塞模型。

传输层 负责 应用传输数据给应用。
端口号: 编号将应用区分开, 80 web 服务器, 22 ssh ,浏览器 临时分配端口号。 TCP 封包上携带了 端口号,接收方识别封包然后发送对应应用

网络层 ip 寻址,路由

数据链路层 为 网络层提供 链路级别传输的支持

物理层: 为 数据链路层 提供二进制传输服务

多路复用 : 一台机器可能只有一份网卡网线,而应用可能有很多。 多个信号,复用一个信道.提升吞吐量,信号相互隔离,并行传输。

应用层多路复用: eg:一个应用可能同时向服务器发送多个请求,多个请求可以 复用 一个 TCP 连接

传输层多路复用: 多个请求并行的发送请求,eg: 多个 TCP 链接复用一条线路,依赖网路层提供多路复用能力

网络层多路复用: 网络层天然支持多路复用

示例:
HTTP 协议, 浏览器打开时,会向服务器发送多个请求,多个请求混合在一起,复用相同连接,数据紧密切互相隔离。