socket 到底是个啥

在这里插入图片描述
哈喽大家好,我是咸鱼

我相信大家在面试过程中或多或少都会被问到这样一个问题:你能解释一下什么是 socket 吗

我记得我当初的回答很是浅显:socket 也叫套接字,用来负责不同主机程序之间的网络通信连接,socket 的表现方式由四元组(ip地址:端口)组成

那么今天,咸鱼将跟大家打开 socket 的神秘大门,不但要搞清楚 socket 的概念,最好还能够了解它的底层实现

我们首先查看一下 socket 的翻译
在这里插入图片描述
我们看到,socket 可以翻译成插座、插头,那现在请想象这么一个场景:给手机充电时,你将充电插头插入电源插座里面,是不是意味着插座与充电插头连接起来了

在计算机世界中,socket 翻译成套接字,通过 socket 我们可以与某台服务器进行连接,而建立连接的过程,你可以脑补成将充电插头插进插座的过程
在这里插入图片描述
在这里插入图片描述

socket 使用场景

假设我们想要将数据从 A 电脑的某个进程传送到 B 电脑的某个进程(比如咸鱼用微信发信息给冰冰)

在这里插入图片描述
那么在与对方聊天的过程中,其实就是这两台电脑中的微信进程相互传输数据的过程

在这个过程中,两台电脑各自调用 socket 方法,然后会得到一个 fd 句柄(socket_fd),这个 fd 句柄就相当于 socket 的身份证号

socket_fd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

得到 fd 句柄之后:

  1. 服务端执行 bind()、listen()、accept() 方法等待客户端建立连接的请求
  2. 客户端执行 connect() 方法向服务端发起连接
  3. 连接建立起来之后,两端都可以执行 send()、recv() 方法来互相传递数据

PS:对于不同的传输层协议,上面这个过程是不一样的,详情可以查看我之前的文章《python 网络编程》

TCP 协议
在这里插入图片描述
UDP 协议
在这里插入图片描述

socket 设计

我们知道了 socket 是用来实现网络传输功能的,它负责不同主机进程之间的网络通信连接

我将上面的问题改一下,把 ”socket 是什么“ 改成 ”如果让你来实现一个网络传输功能,你会怎么设计“

网络传输功能,简单点来讲就是两端服务器之间进行网络通信并互相收发数据,收发数据也就是读写数据
在这里插入图片描述
首先我们会遇到第一个问题:茫茫互联网中你怎么能找到那台梦中情机

聪明的你肯定会想到——ip地址!我们用 ip 地址来定位电脑

找到了你的梦中情机之后,你会发现,一台电脑上面这么多进程,我怎么才能找到与我通信的那个进程(比如说微信)

聪明的你很快就想到了用端口号(port)

可以这么理解,ip 地址是用来定位街区的,而端口号 port 对应这个街区中的门牌号,通过 ip +port 的组合,你可以在茫茫互联网中找到属于你的梦中情机并且与之通信

所以你在设计网络传输功能初期,定义了一个数据结构 sock,sock 里面包含了 ip 和 port 字段(假设用 C 语言实现)
在这里插入图片描述
在 Linux 中(以 CentOS 7举例),在头文件/usr/include/netinet/in.h可以看到负责套接字地址的 sock 结构体
在这里插入图片描述

sin_family 字段为 AF_INET,sin_port 表示端口号,sin_addr 表示 IPv4 地址,是一个 struct in_addr 类型的结构体

sin6_family 字段为 AF_INET6,sin6_port 表示端口号,sin6_addr 表示 IPv6 地址,是一个 struct in6_addr 类型的结构体

解决了定位问题之后,我们知道在计算机网络中有很多协议,这些协议规定了计算机之间的通信方式

比如你是选用可靠的 TCP 协议去进行网络通信,还是相对不可靠的 UDP 协议
在这里插入图片描述
不同的网络协议还对应着不同的网络通信场景,如果你选择了 TCP协议,你还得考虑例如滑动窗口、超时重传这些场景

所以有了 ip 和 port 还不行,你还需要定义新的数据结构用来维护网络协议以及对应的网络场景

又因为不同的网络协议中有一些功能相似的方法(例如收发数据),于是你决定将不同协议中的公共的部分提取出来,通过”继承“的方式来实现功能复用

所以可以先定义一个名为 sock 的数据结构,然后定义”继承“ sock 的各类 sock

**PS:Linux 内核是用 C 语言实现的,在 C 语言中没有继承这个概念,你可以简单将这个继承理解成 xx_sock 基于 sock 进行了扩展,xx_sock 是 sock 的进阶版 **
在这里插入图片描述

  • sock:最基础的结构,用来维护任何网络协议都会用到的收发数据缓冲区(公用部分)
  • inet_sock:负责网络传输功能的 sock,在 sock 基础上加了 TTL(网络生存时间)、ip 地址和端口号这些跟网络传输相关的字段信息
  • inet_connection_sock:面向连接的 sock,在 inet_sock 基础上添加了面向连接的协议里相关字段,比如 accept 队列,数据包分片大小,握手失败,重试次数等;虽然我们现在提到面向连接的协议就是指 TCP,但从设计上 Linux 需要支持扩展其他面向连接的新协议,比如 SCTP 协议,所以说 tcp_sock 则是在这个基础上实现的真正的 TCP 协议专用 sock 结构

上面例子中的这些 sock 都可以在系统上直接找到,以 CentOS 7 为例

#inet_sock
/usr/src/kernels/内核版本.debug/include/net/inet_sock.h

#inet_connection_sock
/usr/src/kernels/内核版本.debug/include/net/inet_connection_sock.h

在这里插入图片描述
现在你用代码实现了这一堆数据结构——sock,不同的 sock 分别实现自己职责内的功能(负责面向连接的数据结构 inet_connection_sock、负责 UDP 协议的数据结构 udp_sock 等等)

但是你需要这些 sock 去跟硬件网卡交互才能实现网络传输的功能,既然需要跟硬件交互,那就说明需要比较高的操作系统权限

同时考虑到性能和安全,这套数据结构不能放在用户态,需要给它放到系统内核里面

既然这套数据结构在内核里,处在用户态的程序想要用这套数据结构来实现网络传输功能该怎么办呢?

除此之外,处在用户态的程序并不关心也不知道你这套数据结构在底层内核是怎么操作的,功能是怎么实现的,它只关心结果

于是你想到了用接口调用的方式——你将一个个功能抽象一个个接口,以后别人只需要调用这些接口,就可以让内核中这一大堆复杂的数据结构去实现指定功能

又因为在 Linux 中一切皆文件,你索性将这些 sock 封装成文件,当用户态的程序去调用你提供的接口时,需要先创建一个 sock 文件

这个新生成的 sock 文件有一个文件句柄 fd,用户态的程序只需要拿着这个 fd 就可以对内核中的 sock 进行操作

# sock 文件句柄 socket_fd
socket_fd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

在这里插入图片描述
上面有说到,你将不同的数据结构(inet_socktcp_sock 等等)抽象成一个个 API 接口,以后别人只需要调用这些 API 接口就可以驱动我们写好的这一大堆复杂的数据结构去进行网络传输

下面列出了一些常见的接口:

  • send
  • recv
  • bind
  • listen
  • connect

到这里,整个网络传输功能就已经基本实现了。上面列举出来的这些方法,其实就是 socket 提供出来的接口

到这里,我们对 socket 有了一个更深的了解——socket 其实相当于一个接口层,它处在内核态和用户态之间:

  • 向上用户态
    • 为处在用户态的程序提供 API 接口,方便用户态程序实现网络传输功能
  • 向下内核态
    • 对网卡进行操作,负责网络传输工作

或者你也可以这么理解,处在用户态的程序通过 socket 提供的接口,将网络传输的这部分工作外包给了 Linux 内核
在这里插入图片描述
我们以 tcp 协议为例子来看下 python 中是如何操作 socket 的

  • 客户端
#创建一个 socket 并获得 socket 文件的句柄
socket_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#调用 connect 接口进行连接
socket_fd.connect(('127.0.0.1', 9999))

#调用 send 接口进行数据传输
socket_fd.send(data)

#调用 close 接口关闭 socket
socket_fd.close()

在客户端中,程序首先调用 socket 提供的 socket 方法创建一个 socket 文件来获得 socket 句柄,然后调用 connect 方法,这时候内核会根据 socket_fd 找到对应的 sock 文件

再根据文件里的信息找到处在内核的 sock 结构,通过 sock 结构与服务端进行三次握手建立连接

连接建立好之后,客户端调用 send 方法来进行数据传输,sock 中定义了一个发送缓冲区和接收缓冲区,其实就是一个链表,链表上面放着一个个等待发送或接收的数据

总结

我们再次回到那个问题——socket 是什么?

sock(或 socket)是操作系统内核提供的一种数据结构,用于实现网络传输功能

基于不同的网络协议以及应用场景,衍生了各种类型的 sock,每个网络层协议都有相应的 sock 结构体来管理该层协议的连接状态和数据传输。各类 sock 操作硬件网卡,就实现了网络传输的功能

为了将这些功能让处在用户态的应用程序使用,不但引入了 socket 层,还将各类功能的实现方式抽象成了 API 接口,供应用程序调用

同时将 sock 封装成文件,应用程序就可以在用户层通过文件句柄(socket fd)来操作内核中 sock 的网络传输功能

这个 socket fd 是一个 int 类型的数字,而 socket 中文翻译叫做套接字,结合这个 socket fd,你是不是可以将其理解成:一套用于连接的数字

而 socket 分 Internet socket 和 UNIX Domain socket,两者都可以用于不同主机进程间的通信和本机进程间的通信,只是前者采用的是基于 IP 协议的网络通信方式,而后者采用的是基于本地文件系统的通信方式

关于 UNIX Domain socket,可以通过 netstat -x 查看
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/12226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用树状图可视化聚类

一般情况下,我们都是使用散点图进行聚类可视化,但是某些的聚类算法可视化时散点图并不理想,所以在这篇文章中,我们介绍如何使用树状图(Dendrograms)对我们的聚类结果进行可视化。 树状图 树状图是显示对象…

大模型混战,阿里百度华为谁将成就AI时代的“新地基”?

从算力基础到用户生态,群雄逐鹿大模型 自2022年stable diffusion模型的进步推动AIGC的快速发展后,年底,ChatGPT以“破圈者”的姿态,快速“吸粉”亿万,在全球范围内掀起了一股AI浪潮,也促使了众多海外巨头竞…

微信为什么使用 SQLite 保存聊天记录

SQLite “只是”一个库,它不是传统意义上的服务器。因此,在某些场合下,它确实不合适。但是,在相当多的其他场合,它却是最合适的选择。SQLite 号称是部署和使用最广泛的数据库引擎。我认为这很有可能,因为 S…

10个镜像网站工具箱供你使用,不注册ChatGPT也能免费使用ChatGPT

ChatGPT已经成为了人工智能技术中备受瞩目的一员,它可以为我们带来更加智能化、个性化的交互体验。对于没有ChatGPT账号或者不想注册账号的人来说,他们可能会错过这种神奇的体验。 而本篇文章就帮大家解决这个问题,不用登录ChatGPT账号&…

Doris(9):删除数据(Delete)

Delete不同于其他导入方式,它是一个同步过程。和Insert into相似,所有的Delete操作在Doris中是一个独立的导入作业,一般Delete语句需要指定表和分区以及删除的条件来筛选要删除的数据。 Doris 目前可以通过两种方式删除数据: DE…

使用Schrödinger Python API系列教程 -- 介绍 (一)

使用Schrdinger Python API系列教程 – 介绍 (一) 本文档可从Schrdinger网站www.schrodinger.com/pythonapi访问。 从Python文档字符串生成的完整API文档可以在这里访问 介绍 在最高级别上,Schrdinger Python API提供了一个基本的分子结构类,并允许与…

【JavaEE】关于synchronized总结-Callable用法及JUC的常见问题

博主简介:想进大厂的打工人博主主页:xyk:所属专栏: JavaEE初阶synchronized原理是什么?synchronized到底有什么特点,synchronized的锁策略是什么,是怎么变化的呢?本篇文章总结出, Synchronized 具有以下特性…

HyperWorks2021软件安装教程

下载软件 https://www.xsoftnet.com/share/a0004MWyQAg9r.html产品介绍: HyperWorks一款功能强大的开放式架构仿真软件。拥有先进的技术以及高性能、高效和创新的产品,为用户提供了设计、仿真和制造等服务。支持电磁分析设计、材料建模制造、多物理场分…

【数据结构】二叉树链式结构

🚀write in front🚀 📜所属专栏:初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对…

18 隐私模式下面发送 http 请求不成功

前言 是这样的一个情况, 最近 我们服务存在这样的一个问题 是在登录界面, 假设我用户名 或者 密码输入错误, 能够得到真确的结果, 拿到了 正常的 http 响应, 回来 "用户名 或者 密码 不正确 " 但是 假设是在 隐私模式下面, 同样的输入, 同样的服务, 但是结果 不一…

【配电网故障重构SOP】基于二阶锥松弛的加光伏风机储能进行的配电网故障处理和重构【考虑最优潮流】(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Java多线程基础学习(一)

1. 创建线程 1.1 通过构造函数:public Thread(Runnable target, String name){} 或:public Thread(Runnable target){} 示例: Thread thread1 new Thread(new MyThread(), "mythread"); class MyThread extends Thread(){public void …

联盟链是虚构的?没有用的?用FISCO BCOS来展示链委员这件事

前言 当前区块链大都使用的是投票决定这种方法,但是如何使现实中的投票转换到区块链中,如何让举手表决变得更加智能,如何让投票透明、安全、权威,这是区块链的一大设计思路,有很多人觉得联盟链是个梦,是个虚…

计算机网络简史

ARPANET的发展 互联网最早的雏形 1931-ARPANET设计 互联网名人堂 1965-packet switching(分包交换) 1969 第一个RFC(Request for Comments)(开始通过APPANET发布)第一个接口信息处理单元(Interface Message Processor)(下图,节…

制造企业该如何选择MES生产管理系统?盘点四大生产管理系统软件

本文将介绍:1、如何选择MES(生产管理系统);2、盘点四款好用的生产管理系统 生产管理系统即MES(Manufacturing Execution System),制造执行系统。是面向车间生产的管理系统。在产品从工单发出到成品完工的过程中,MES系…

提取图像特征方法总结 是那种很传统的方法~

目录 写在前面 一、SIFT(尺度不变特征变换) 1.SIFT特征提取的实质 2.SIFT特征提取的方法 3.SIFT特征提取的优点 4.SIFT特征提取的缺点 5.SIFT特征提取可以解决的问题: 二、HOG(方向梯度直方图) 1.HOG特征提取…

webgl-图形非矩阵旋转

知识拓展 由(x1,y1)旋转β角度到(x2,y2) 根据圆极坐标方程 x1 r*cosα y1 r*sinα 可得 x2 r*cos(α β) r*cosα*cosβ - r*sinα*sinβ,因为x1 r*cosα,y1 r*sinα,所以x2 x1*cosβ -y1*sinβ…

Linux 提权学习

提权的目的是获取 root 权限 root 权限可获取 shadow 文件中的密码 Hash,若内网环境中存在「账户/密码复用」的情况,可用于横向扩展 暴力破解 suid 提权 内核漏洞提权 定时任务提权 sudo 提权 第三方服务提权(docker、mysql、redis、NFS提权…

【C++】结构体嵌套结构体

目录 1、缘起 2、结构体嵌套结构体 3、总结 1、缘起 结构体嵌套结构体 是一种数据组织方式,就像 俄罗斯套娃 一样,一个数据结构可以包含另一个数据结构。这种嵌套结构使得程序可以更加灵活地处理数据,从而更好地满足复杂的需求。类比生活中…

Can‘‘t connect to MySQL server on localhost (10061)解决方法

首先检查MySQL 服务没有启动》如果没有启动,则要启动这个服务。 有时候安装mysql后使用mysql命令时报错 Cant connect to MySQL server on localhost (10061),或者用net start mysql 时报服务名无效,一般是因为mysql服务没有启动。 打开 powe…
最新文章