到底啥是Socket?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了到底啥是Socket?相关的知识,希望对你有一定的参考价值。

参考技术A 本系列文章前面那些主要讲解的是计算机网络的理论基础,但对于即时通讯IM这方面的应用层开发者来说,跟计算机网络打道的其实是各种API接口。

本篇文章就来聊一下网络应用程序员最熟悉的Socket这个东西,抛开生涩的计算机网络理论,从应用层的角度来理解到底什么是Socket。

对于 Socket 的认识,本文将从以下几个方面着手介绍:

1) Socket 是什么;

2) Socket 是如何创建的;

3) Socket 是如何连接的;

4) Socket 是如何收发数据的;

5) Socket 是如何断开连接的;

6) Socket 套接字的删除等。

特别说明: 本文中提到的“Socket”、“网络套接字”、“套接字”,如无特殊指明,指的都是同一个东西哦。

Socket 是什么

一个数据包经由应用程序产生,进入到协议栈中进行各种报文头的包装,然后操作系统调用网卡驱动程序指挥硬件,把数据发送到对端主机。

我们大家知道,协议栈其实是位于操作系统中的一些协议的堆叠,这些协议包括 TCP、UDP、ARP、ICMP、IP等。即时通讯开发可以找蔚可云开发。

通常某个协议的设计都是为了解决特定问题的,比如:

1) TCP 的设计就负责安全可靠的传输数据;

2) UDP 设计就是报文小,传输效率高;

3) ARP 的设计是能够通过 IP 地址查询物理(Mac)地址;

4) ICMP 的设计目的是返回错误报文给主机;

5) IP 设计的目的是为了实现大规模主机的互联互通。

应用程序比如浏览器、电子邮件、文件传输服务器等产生的数据,会通过传输层协议进行传输。而应用程序是不会和传输层直接建立联系的,而是有一个能够连接应用层和传输层之间的套件,这个套件就是 Socket 。

应用程序的下面: 就是操作系统内部,操作系统内部包括协议栈,协议栈是一系列协议的堆叠。

操作系统下面: 就是网卡驱动程序,网卡驱动程序负责控制网卡硬件,驱动程序驱动网卡硬件完成收发工作。

在操作系统内部有一块用于存放控制信息的存储空间,这块存储空间记录了用于控制通信的控制信息。其实这些控制信息就是 Socket 的实体,或者说存放控制信息的内存空间就是Socket的实体。

这里大家有可能不太清楚所以然,所以我用了一下 netstat 命令来给大伙看一下Socket是啥玩意。

Socket 是如何创建的

通过上节的讲解,现在你可能对 Socket 有了一个基本的认识,先喝口水,休息一下,让我们继续探究 Socket。

现在我有个问题, Socket 是如何创建的呢?

Socket 是和应用程序一起创建的。

应用程序中有一个 socket 组件,在应用程序启动时,会调用 socket 申请创建Socket,协议栈会根据应用程序的申请创建Socket:首先分配一个Socket所需的内存空间,这一步相当于是为控制信息准备一个容器,但只有容器并没有实际作用,所以你还需要向容器中放入控制信息;如果你不申请创建Socket所需要的内存空间,你创建的控制信息也没有地方存放,所以分配内存空间,放入控制信息缺一不可。至此Socket的创建就已经完成了。

Socket创建完成后,会返回一个Socket描述符给应用程序,这个描述符相当于是区分不同Socket的号码牌。根据这个描述符,应用程序在委托协议栈收发数据时就需要提供这个描述符。

Socket 是如何连接的

Socket创建完成后,最终还是为数据收发服务的。但是,在数据收发之前,还需要进行一步“连接”(术语就是 connect),建立连接有一整套过程。

实际上这个“连接”是应用程序通过 TCP/IP 协议标准从一个主机通过网络介质传输到另一个主机的过程。

Socket刚刚创建完成后,还没有数据,也不知道通信对象。

在这种状态下: 即使你让客户端应用程序委托协议栈发送数据,它也不知道发送到哪里。所以浏览器需要根据网址来查询服务器的 IP 地址,查询到目标主机后,再把目标主机的 IP 告诉协议栈。至此,客户端这边就准备好了。

在服务器上: 与客户端一样也需要创建Socket,但是同样的它也不知道通信对象是谁,所以我们需要让客户端向服务器告知客户端的必要信息: IP 地址和端口号 。

现在通信双方建立连接的必要信息已经具备,可以开始“连接”过程了。

首先: 客户端应用程序需要调用 Socket 库中的connect方法,提供 socket 描述符和服务器 IP 地址、端口号。

以下是connect的伪码调用:

1connect(<描述符>、<服务器IP地址和端口号>)

这些信息会传递给协议栈中的 TCP 模块,TCP 模块会对请求报文进行封装,再传递给 IP 模块,进行 IP 报文头的封装,然后传递给物理层,进行帧头封装。

之后通过网络介质传递给服务器,服务器上会对帧头、IP 模块、TCP 模块的报文头进行解析,从而找到对应的Socket。

Socket收到请求后,会写入相应的信息,并且把状态改为正在连接。

请求过程完成后: 服务器的 TCP 模块会返回响应,这个过程和客户端是一样的

Socket 是如何收发数据的

当控制流程上节中的连接过程回到应用程序之后,接下来就会直接进入数据收发阶段。

数据收发操作是从应用程序调用 write 将要发送的数据交给协议栈开始的,协议栈收到数据之后执行发送操作。

协议栈不会关心应用程序传输过来的是什么数据,因为这些数据最终都会转换为二进制序列,协议栈在收到数据之后并不会马上把数据发送出去,而是会将数据放在发送缓冲区,再等待应用程序发送下一条数据。

为什么收到数据包不会直接发送出去,而是放在缓冲区中呢?

因为只要一旦收到数据就会发送,就有可能发送大量的小数据包,导致网络效率下降(所以协议栈需要将数据积攒到一定数量才能将其发送出去)。

至于协议栈会向缓冲区放多少数据,这个不同版本和种类的操作系统有不同的说法。

Unix Socket - 啥是socket(套接字)?

参考技术A         套接字允许在相同或不同机器上的两个不同进程之间进行通信。更准确地说,它是一种使用标准Unix文件描述符与其他计算机通信的方法。在Unix中,每个I/O操作都是通过写入或读取文件描述符来完成的。文件描述符只是一个与打开的文件相关联的整数,它可以是一个网络连接、一个文本文件、一个终端或其他东西。

        对于程序员来说,套接字的外观和行为很像底层的文件描述符。这是因为read()和write()等命令使用套接字的方式与使用文件和管道的方式相同。

        socket最初是在2.1BSD中引入的,随后在4.2BSD中被细化为当前的形式。目前大多数UNIX系统版本都提供了套接字特性。

        在CS应用程序框架中使用Unix套接字。服务是一个根据客户端的请求执行某些功能的进程。大多数应用程序级协议,如FTP、SMTP和POP3,都利用套接字在客户机和服务器之间建立连接,然后进行数据交换。

        有四种类型的套接字可供用户使用。前两种是最常用的,后两种很少使用。

        假定进程只在相同类型的套接字之间通信,但没有限制阻止不同类型的套接字之间通信。

         流套接字 ——保证在网络环境中交付。如果您通过流套接字发送三个项目“A, B, C”,它们将以相同的顺序到达-“A, B, C”。这些套接字使用TCP(传输控制协议)进行数据传输。如果无法投递,发送者将收到一个错误指示符。数据记录没有任何边界。

         数据包套接字 ——不能保证在网络环境中交付。它们是无连接的,因为你不需要像在流套接字中那样有一个打开的连接——你建立一个带有目标信息的包并将它发送出去。它们使用UDP(用户数据包协议)。

         原始套接字 ——这些为用户提供对底层通信协议的访问,这些协议支持套接字抽象。这些套接字通常是面向数据包的,尽管它们的确切特征取决于协议提供的接口。原始套接字不是为一般用户设计的;它们主要是为那些有兴趣开发新通信协议或访问现有协议中一些更神秘的设施的人提供的。

         顺序包套接字 ——它们类似于流套接字,不同的是记录边界被保留。该接口仅作为网络系统(NS)套接字抽象的一部分提供,并且在大多数严肃的NS应用程序中非常重要。顺序包套接字允许用户对一个包或一组包操纵序列(SPP)或网络数据包协议数据报协议(IDP)的报头,通过编写一个标准头,连同任何要发送的数据,或者通过指定一个默认的报头使用所有即将输出的数据,并允许用户接收传入的数据包的报头。

以上是关于到底啥是Socket?的主要内容,如果未能解决你的问题,请参考以下文章

nodejs:会话存储在哪里?啥是连接蒙戈?

Http 和 Socket 到底是哪门子亲戚?

Python干货socket中的listen()参数(数字)到底代表什么?

我们常说的短连接长连接和socket和http到底有什么关系

socket到底是啥?网关(Gateway)是啥?网络通信的核心是啥?

服务器到底是一个什么样的概念