IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 网络编程(二)—— socket套接字和地址 -> 正文阅读

[系统运维]网络编程(二)—— socket套接字和地址

在这里插入图片描述

🍓什么是socket?🍓

在网络编程中经常跟socket这个单词打交道,译为 “插座、插口”,而我们常称为”套接字“

联想现实生活中的插座、插口,如电脑的USB接口,其作用就是作为两个对象之间的数据收发或能量传递;同理,在网络编程中,socket就是通过插口接入的方式,快速的完成网络连接以及数据的收发。

在这里插入图片描述

上图是网络编程中,TCP客户端和服务器工作的核心逻辑。

网络编程中的基本流程:

  1. 在客户端发起连接请求前,服务器端先初始化
    1. 初始化socket
    2. 执行bind函数,将服务能力绑定在已知的地址和端口
    3. 执行listen函数,将基础socket转换为服务器端特有的socket
    4. 完成上述三个步骤后,阻塞在accept函数上,等待客户端发起连接请求
  2. 待服务器端初始化完成后,客户端发起连接请求
    1. 初始化socket
    2. 执行connect函数向服务器端的地址和端口发起连接请求
  3. 完成上述两个步骤后,此时客户端和服务器端已完成连接的建立,开始传输数据 注意:一旦连接建立,数据的传输就不是单向的,而是双向的,这是TCP特点之一
    1. 客户端进程向操作系统内核申请write字节流操作,将字节流通过网络设备传输到服务器端
    2. 服务器端从内核得到信息,将字节流从内核读入到进程中,开始后续的处理,完成后以同样方式将结果返回客户端
  4. 当客户端和服务器端完成交互动作后,需要和服务器端断开连接时,就需要执行close函数
    1. 系统内核通过原先的连接链路向服务器端发送一个FIN包,服务器收到后执行被动关闭,然后执行close函数
    2. 服务器端发送的FIN包没有被客户端接收到时,原先的连接仍是正常的,还可以继续进行数据的发送,只有在接收到FIN包时,整个链路才会完全关闭

上面四个步骤中的前两个步骤,就是平时常说的TCP三次握手。在这一系列的操作中,都始终通过一个媒介进行交流,就是socket。

🍓通俗的解释socket🍓

在这里插入图片描述

关于TCP网络交互以及数据传输的流程,大家通常都比喻为打电话,顺着这个思路,代入场景进行联想,就可以很好的从平常生活体验中理解网络编程

记住上面的核心逻辑图,按照上述的网络编程基本流程进行沉浸式代入理解

  1. 服务器端先初始化
    1. socket函数:我们手里的手机
    2. bind函数:比作我们去办一张手机卡,将手机卡插入到手机中,使得这个手机卡和手机绑定在一起,这样别人就可以通过这个号码,找到拿着这个手机的我们
    3. listen函数:就像我们手机电话铃声响起,知道有人给我们打电话这个信息
    4. accept函数:我们拿起手机,点击接听后,等待对方的消息
  2. 客户端初始化
    1. socket函数:别人的手机
    2. connect函数:别人拿起手机,拨通我们的手机号
  3. 上述两个步骤后,此时连接建立。我们能听到对方说话,对方也能听到我们说话
    1. 客户端write函数:别人发起问候:”你好!是靓仔吗?“
    2. 服务器端read函数:我们听到别人真挚的问候,确认通话正常
    3. 服务器端write函数:我们回到:”是的,我是靓仔。有事请说……“
    4. 客户端read函数:别人接收到我们的回复,确认通话正常
    5. 客户端write函数:别人:”下面我要通知你的是恭喜你完成四级英语考试,成绩为424分……“
    6. ……
  4. 当别人事情交待完成后,要结束本次通话了
    1. 客户端close函数:别人:”这是我要说的所有事了,如果你没有事了,我们就结束此次通话吧!“,此时状态为等待挂断(别人没听到我们的回复前,不确定我们是否还有事,所以会处于等待关闭状态)
    2. 服务器端close函数:我们:”我这边没有什么事了,谢谢你的告知!“,挂断了电话。此时我们是已经挂断了电话,通话处于半关闭状态
    3. 客户端:接收到我们的挂断信息后,别人也挂断了电话。本次通话结束

在整个通话过程中,手机(socket)是我们交流的工具,这就是socket的作用。

🍓套接字地址格式🍓

什么是套接字地址?在前面我们说到了,网络通信的关键在于使用socket建立连接,而连接的基础是双方地址已知,否则就会导致无头苍蝇到处飞。套接字地址就是前面通俗解释中所说的bind()函数中的电话卡操作,而现实中电话又分两种模式:1. 常用手机电话(如16866666666);2. 固定电话(如(010)123456)

网络编程中,套接字地址格式通常分为三类:

  1. AF_LOCAL:本地地址,对应Unix套接字,由名字可知常用于本地socket通信
  2. AF_INET:互联网常用的IPv4地址格式
  3. AF_INET6:为解决IPv4地址数量不足而新增的IPv6地址格式

上面三种套接字类型中都含有一个共同点:”AF_“,AF其实是 “Address Family” 的英文单词缩写,译为地址族;还有一种网络编程中常见的族:”PF”,即“Protocol Family”,译为协议族。通常AF用于初始化socket地址,PF用于初始化scoket。通过<sys/socket.h>头文件,可以找到各种地址族的宏定义


/* Macro definitions of various address families  */
#define AF_UNSPEC PF_UNSPEC
#define AF_LOCAL  PF_LOCAL
#define AF_UNIX   PF_UNIX
#define AF_FILE   PF_FILE
#define AF_INET   PF_INET
#define AF_AX25   PF_AX25
#define AF_IPX    PF_IPX
#define AF_APPLETALK  PF_APPLETALK
#define AF_NETROM PF_NETROM
#define AF_BRIDGE PF_BRIDGE
#define AF_ATMPVC PF_ATMPVC
#define AF_X25    PF_X25
#define AF_INET6  PF_INET6

🍅IPv4🍅


/* IPV4套接字地址,32bit值.  */
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };
  
/* 描述IPV4的套接字地址格式  */
struct sockaddr_in
  {
    sa_family_t sin_family; /* 16-bit */
    in_port_t sin_port;     /* 端口号  16-bit*/
    struct in_addr sin_addr;    /* Internet address. 32-bit */


    /* 这里仅仅用作占位符,不做实际用处  */
    unsigned char sin_zero[8];
  };

上面是IPv4套接字地址格式的结构体定义。

  1. 16 bit的 sin_family 字段:IPv4中就是前面所说的AF_INET
  2. 16 bit的 sin_port 字段:支持最大2^16次方个数的端口号,即每个地址最多可有65536个端口号
  3. 32 bit的 sin_addr 字段:最多支持2^32次方(约为42亿)个ip地址,这是一个非常大的数量,但是对于全球来说,显然不够,所以就有了IPv6的设计(注意该字段中的类型还有结构体定义)

小问题:端口号中所有端口都可以随意使用吗?

不是的,上一节知识里有提到过一个知识点——众所周知的端口号。在这里解释一下什么是众所周知的端口号,其实就是互联网发展初期,大家约定好用于某些途径一定会占用的端口号,已经被对应服务广为使用,其他人不能在随意使用这些端口号。具体有哪些保留端口可以百度一下保留端口

🍅IPv6🍅


struct sockaddr_in6
  {
    sa_family_t sin6_family; /* 16-bit */
    in_port_t sin6_port;  /* 传输端口号 # 16-bit */
    uint32_t sin6_flowinfo; /* IPv6流控信息 32-bit*/
    struct in6_addr sin6_addr;  /* IPv6地址128-bit */
    uint32_t sin6_scope_id; /* IPv6域ID 32-bit */
  };

上面是IPv6套接字地址格式的结构体定义。

  1. 16 bit的 sin_family 字段:IPv6中即为AF_INET6
  2. 16 bit 的 sinz-port 字段 :与IPv4中定义的范围一样
  3. 32 bit的流控信息字段 :该字段暂时未用到
  4. 128 bit的 sin6_addr 字段:相比IPv4的32 bit,IPv6的 地址字段增大到了 128 bit,这就解决了IPv4地址数量不足的问题
  5. 32 bit的域ID字段 :该字段暂时未用到

🍅本地套接字地址🍅


struct sockaddr_un {
    unsigned short sun_family; /* 固定为 AF_LOCAL */
    char sun_path[108];   /* 路径名 */
};

上面是AF_LOCAL的地址格式结构体定义。

  1. sun-family:固定为AF_LOCAL地址族
  2. sun_path :最长108字节的 路径地址

从第二个字段就可以看出这是一个用于本地进程间通信的地址格式,直接通过本地文件路径进行通信

🉑总结🉑

  1. socket 是我们用来建立连接,传输数据的唯一途径
  2. 网络通信就需要用到地址族和地址,地址族用于双方约定的格式,地址用于双方寻址。对远程网络通信而言,只知道地址还不行,还需要用到端口来锁定唯一的目标;对于本地通信,文件路径即决定了唯一的目标,所以IPv4/IPv6需要用到端口号,而本地套接字不需要用到端口号
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:49:45  更:2022-04-01 23:53:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 23:32:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码