关于网络编程:Socket简介和IO多路复用

8次阅读

共计 3509 个字符,预计需要花费 9 分钟才能阅读完成。

最近在学 nio,遇到了多路复用这个概念,而后我又想了想本人大学学的《计算机网络》,那个时候学网络总是感觉是一堆空洞洞的实践,因为我学到的和实际没有分割在一起。学习 NIO 的过程中,感觉对计算机网络又有新的意识,于是打算整顿一下对网络的认知。留神本篇文章只是概论,并不会探讨具体的协定,只是搭建一个了解网络的简略模型。

[TOC]

程序和协定的桥梁

现在的互联网曾经很遍及了, 每天的地铁上都会有许多人在用手机做很多事件,比方浏览新闻、玩王者光荣、刷抖音,这些都是在应用网络应用程序。乏味的是,所有的网络应用都是基于基本相同的编程模型,有着类似的整体逻辑构造,并且依赖雷同的编程接口。
网络是很简单的零碎,在这里我能说介绍的是一点点皮毛,我的指标是从程序员的角度建设一个容易了解的网络通信模型。

当咱们说起网络通信时,事实上说的是位于两台计算机上的过程之间通过互联网替换信息,如果说咱们将网络当做一个黑盒子的话。每个网络应用都是基于客户端 - 服务器模型的,服务器管控着某些资源,并且通过操纵这些资源向客户端提供某种服务。

粗略的说, 过程就是正在运行中的程序,那咱们当初要使咱们的应用程序取得互联网反对,或者说就是要进行网络通信,然而咱们又不能间接应用曾经标准化了的互联网的利用协定,那咱们该当怎么做呢? 要答复这个问题,实际上就要理解上面介绍的 Socket,事实上更齐备的答复应该由《网络编程》给出。

Socket

通常各个高级编程语言都有对应的接口或者类库,供开发者调用。然而事实上程序还是须要借助操作系统能力取得互联网的反对。

对计算机而言,网络又是一种 I / O 设施,是数据源和接管方。网卡提供了到网络的物理接口 (什么你不晓得什么叫网卡?,等着我)。从网络上接管的数据从网卡通过 I / O 和内存总线复制到内存,通常 通过 DMA 传送。类似地,数据也能从内存复制到网络。
看过我的《操作系统与通用计算机组成原理简论》这篇文章的应该晓得程序是无奈间接接触硬件的,程序只能通过操作系统提供的服务,来进行 I / O 操作。同样的从网络上获取信息,发送信息,也是须要调用操作系统提供的接口的。

当初 TCP/IP 协定软件曾经驻留在操作系统中。因为 TCP/IP 协定族被设计成能运行在多种操作系统的环境中,因而 TCP/IP 协定规范没有规定应用程序与 TCP/IP 协定软件如何接口 (调用) 的细节,而是容许零碎设计者可能抉择无关 API 的具体实现细节。

目前来说只有几种可供应用程序应用的 TCP/IP 的利用程序接口,最驰名的就是美国加利福利亚大学伯克利分校为 Berkeley UNIX 操作系统定义的 API,被称为套接字接口(socket interface)。微软在其操作系统中采纳了套接字 API,然而有一点不同,咱们称之为 Windows Socket。AT&T 的 Unix System V 版本定义的接口,简写为 TLI(Transport Layer port)

咱们能够认为套接字作为过程和运输层协定之间的接口,像上面这样。

请留神: 在套接字以上的过程是受利用程序控制的,而在套接字以下则属于操作系统的管制。因而,只有程序要应用 TCP/IP 协定进行通信,它就必须调用操作系统提供的网络通信接口。这里的套接字是一个相对来说有些形象的概念,那么该怎么了解这里的套接字呢? 为什么说这里的套接字? 因为在其余语境下套接字领有其余语义,然而也叫套接字。我认为这里的套接字的就是一个规定、协约、机制 : 当程序须要应用网络通信时,必须首先调用操作系统提供的 Socket 接口,也能够称之为收回 Socket 零碎调用,申请操作系统创立一个 ” 套接字 ”。这个调用的实际效果就是申请操作系统把网络通信所须要的的一些资源 (CPU 工夫, 网络带宽、存储器空间等) 调配给该利用过程。操作系统为这些资源的总和创立一个套接字描述符的号码 (小的整数) 来示意,而后将这个套接字描述符返回给利用过程。尔后,利用过程所进行的网络操作 (建设连贯、收发数据、调整网络通信参数等) 都必须应用这个套接字描述符。

所以简直所有的网络调用都把这个套接字描述符作为作为第一个参数,在调用操作系统提供的网络通信接口时,通过套接字描述符,就能够辨认应该应用哪些资源来实现利用过程所申请的服务。

通信结束后,应用程序通过一个敞开套接字的 close 调用告诉操作系统回收与该套接字描述符相干的所有资源。

这里可能有些形象,艰深的说,咱们能够将 Socket 了解为一份合约,这份合约由操作系统提供,合约上规定了网络通信的一些事宜,利用过程遵循此合约,即可享受到操作系统提供的网络通信服务。

一个操作系统同时存在多个网络应用程序是非常天然的,因而须要有一个寄存套接字描述符的表,而每一个套接字描述符都有一个指针指向寄存套接字的地址。

Socket 的不同语义

Socket 在不同的语境,有不同的语义。

  • 在 TCP 连贯下的语义

咱们晓得 TCP 将连贯作为最根本的形象,每一套 TCP 连贯有两个端点,TCP 连贯的端点即为套接字(Socket)。依据 RFC 793 的定义: 端口号拼接到 IP 地址即形成了套接字。因而套接字的示意办法是在点分十进制的 ip 地址前面写上端口号,两头用冒号或逗号隔开。总之咱们有

socket = (ip 地址: 端口号)
每一条 TCP 连贯惟一地被通信两端的套接字所确定。

  • 高级语言拜访互联网的接口,即运输层和应用层的一个接口,也能够称之为 socket.

java 中就有一个叫 Socket 的类。

  • 操作系统内核中与互联网通信的加利福利亚大学伯克利分校实现,称之为 socket 实现。

网络通信的过程

咱们以操作系统提供的 TCP 协定服务来介绍,网络通信的过程。

  • 套接字 期待连贯所做的筹备工作

首先过程调用操作系统提供的服务创立套接字,操作系统将对应的资源分配给对应申请的过程。在套接字创立后它的端口号和 IP 地址都是空的。因而利用过程须要绑定 ip 地址和端口号来指明套接字的本地地址,这里的绑定也是操作系统提供的服务,调用绑定服务事实上就是将 ip 地址和端口号填写调已创立的套接字中。

咱们晓得 TCP 是面向连贯的,那么此时仅仅创立套接字是不够的,该当调用操作系统提供的监听服务(咱们经常称为 listen),将套接字设置为被动形式,以便随时承受客户的服务申请。UDP 服务因为只提供无连贯服务,不应用 listen 服务。

再接着应用程序就调用承受服务, 这个承受咱们经常称之为 accept 服务,以便把连贯申请提取进去。

调用 accept 服务之后要实现的动作比拟多,因为服务器必须同时解决多个连贯。这块在 java 的计划是多线程来解决,一个线程解决一个连贯,当连贯过多的时候,咱们就须要换别的思路了,这也就是下文提到的多路复用。

  • 数据传送阶段

这个其实就是连贯建设之后,客户端和服务端相互发送数据的过程。

  • 连贯开释阶段

咱们上文讲到创立套接字是要向操作系统申请资源的,咱们也晓得 TCP 的连接时间不可能无限度的始终连贯上来,当连贯敞开,就须要开释向操作系统申请的资源。

I/O 多路复用

咱们晓得在客户端比拟少的时候,采纳多线程去解决客户端的连贯是没有什么问题的,这种模型个别被称为多线程并发模型,
线程在某种意义上能够称之为轻量级的过程,所以这种模型也被称为多过程并发模型。

当初经常也是多核 CPU,能充沛的利用多核。然而这个模型也有不合理之处,咱们须要为每一个客户端创立一个线程。不论客户端是否有发送数据。客户端一旦变多,这种开销就变得难以承受起来。

咱们来剖析一下这个模型不合理在哪里? 服务端始终在随时监听客户端的连贯,当连贯建设实现之后,服务端不论客户端有没有数据发过来就随即启动一个线程解决这个客户端的通信。很多线程在数据还未到来就处于闲暇状态,相当的节约。改良的计划就是抽出一个线程来记录这些客户端的状态。这个线程就是管理者,连贯建设好了,数据还没来,先不启动线程,有数据来了再解决,这样的益处就是缩小了线程开销,不用是每一个客户端都一个线程,建设连贯,客户端的数据总会有先后顺序,谁先到来我就解决谁。
再反复一遍,连贯就绪了服务端过程临时不解决,哪个客户端的数据到来就解决谁。这就是多路复用,英文名是 I/O multiplexing。

Linux 下的 select,poll,epoll 都是 I / O 多路复用的具体实现,为什么会有三个呢?因为这三个的呈现是有先后顺序的。
widnows 下多路复用的具体实现为 select function (winsock2.h) – Win32 apps | Microsoft Docs

具体的能够参看《IO 多路复用是什么意思?》

参考资料:

  • 《计算机网络》(第 7 版) 谢希仁著
  • 《深刻了解计算机系统》第三版
  • 《IO 多路复用是什么意思?》
  • 深刻学习了解 IO 多路复用
正文完
 0