计算机网络(二) —— 网络编程套接字
目录
一,认识端口号
1.1 背景
1.2 端口号是什么
1.3 三个问题
二,认识Tcp协议和Udp协议
三,网络字节序
四,socket编程接口
4.1 socket常见API
4.2 sockaddr结构
一,认识端口号
1.1 背景
问题:在进行网络通信的时候,是不是我们的的两台机器在通信呢?
解答:我们把软件下载下来安装好,但是不打开,不耗费流量;只有当我们打开,它加载的时候才会耗流量。所以,网络通信的时候,本质是应用层在通信
- 网络协议的下三层:网络层,传输层,数据链路层,主要解决数据安全可靠地被送到远端机器
- 用户使用应用层软件,完成数据地发送和接收,而软件要进行通信就要先启动起来,而启动一个软件也就是进程创建
- 所以日常我们网络通信的本质:就是“进程间通信”,两个进程间要通信就是让两个进程看到同一份资源,这个资源就是网络,而这个网络再具体一点就是网络协议栈
问题: 当传输层即将把数据交给应用层时,但是此时应用层有很多应用,它咋知道要把数据交给哪个应用呢?
解答:所以上层要和传输层达成一种方案,让数据能够准确地交给上层,这个方案叫做“端口号”
1.2 端口号是什么
端口号:是传输层协议的内容,是一个2字节16位的整数,就是4个数字,它用来标识一个进程,告诉操作系统,当前这个数据从传输层要交给应用层的哪一个应用
- 端口号无论对于客户端还是服务器,都能唯一地标识该主机上的一个网络应用层的进程,这点类似于进程的PID,一个端口号只能被一个进程占用
- 在公网上,ip地址能表示唯一的一台主机,端口号(port),用来标识该主机上的唯一一个进程,所以 ip + port = 标识全网唯一的一个进程。
- 所以客户端和服务器都要有自己的ip和port,这种基于ip + port 的通信方式,我们叫做socket,后面会讲
1.3 三个问题
问题:端口号和我们的进程pid有什么区别,两者似乎都能标识该主机上进程的唯一性,那为什么不用pid要用端口号?
解答:
- 不是所有的进程都需要网络通信,但是所有进程都要有pid --> 告诉我们网络是需要单独设计的
- 实现端口号,是为了实现系统和网络的功能解耦,因为系统可能会变,当两者分开设计后,一方收影响就不会影响对方或者对对方的影响大大降低
问题:服务器和客户端是如何知道对方的端口号的?
解答:
首先是客户端如何知道服务器端口号的:
- 服务器和端口号都是同一家公司开发的,所以要想客户端知道端口号,那么这个端口号必须是众所周知的,精心设计的被客户端知晓的
- 这个一般由开发商做的,安装的时候将端口号或者ip直接内置进去了
然后是服务器如何知道客户端端口号的:
- 每次请求都是客户端主动发起的,所以让服务器知道客户端端口号是比较容易的
问题:传输层是如何根据端口号讲数据准确交给应用层众多进程中的那一个对应进程的?
解答:
- 操作系统会在传输层给我们形成一张哈希表,里面存的都是各个进程PCB的指针
- 首先进程绑定端口号的时候,就根据哈希算法找到对应位置,如果这个位置没有PCB指针,就把该进程的PCB指针存进去,当把PCB指针放进哈希表时,就可以认为该进程绑定了端口号
- 然后客户端的报文到了服务器的传输层时,传输层就拿着报文中的端口号在哈希表里做哈希运算,找到哈希表对应位置的进程PCB指针,进而找到对应进程,完成传输层将数据交给应用层的某个具体进程
- 一个进程可以绑定多个端口号,但是一个端口号只能绑定一个进程,因为哈希表是这样规定的,比如哈希表多个位置可以放同一个指针,但是同一个位置只能放一个指针
二,认识Tcp协议和Udp协议
网络协议栈是贯穿整个体系结构的,在操作系统层,应用层和驱动层都有自己的协议。而离我们普通程序员最近的就是使用系统调用接口实现网络通信了,所以离我们最近的就是传输层,传输层应用最广泛最受欢迎的两种协议就是TCP协议和UDP协议了
TCP协议
Tcp:传输控制协议(Transmission Control Protocol),是一种面向连接的,可靠的,基于字节流的传输层协议。
- 如果两台主机想通过Tcp进行数据通信,那么必须先建立好连接道路,并确保建立成功后才进行数据传输
- 同时,Tcp协议也是保证数据传输可靠的协议,数据在传输过程中如果出现了丢包,乱序等情况,Tcp协议都有对应的解决方法,具体我们后面再讲
UDP协议
UDP:用户数据报协议(User Datagram Protocol),是一种无需建立连接,不可靠的,面向数据报的传输层协议
- 如果两台主机要使用Udp通信,无需建立连接,一方根据IP和端口直接就将数据发送给对方,这也就意味着Udp协议是不可靠的,中途出现丢包,乱序等情况,Udp都不会去处理
问题:Tcp比Udp可靠,那为啥传输层要这两种协议同时存在呢?
解答:
- 其实这里的“可靠”和“不可靠”都是中性词,无褒贬含义,就和化学里的“惰性”一样,只是描述某个东西的物理特征,并不是说这个物理懒之类的
- 保证可靠是需要成本的,而相反,不可靠相反的就是简单,TCP在比如说银行转账,微信支付的时候,底层必须是TCP协议,而UDP通常在直播,信息流视频流做数据大量派发的场景有用
- TCP虽然是可靠传输,但并不是万能的,它是保证在网络连通且链接较强的时候处理一些数据丢失问题,也就意味着Tcp的传输效率是没Udp高的,Tcp会在底层做更多的工作
三,网络字节序
计算机在存储数据时是有大小端的概念的:
- 大端:数据的高字节内容保存在内存的低地址处,低字节保存在内存的高字节处
- 小端:数据的低字节内容保存在内存的低地址处,高字节保存在内存的高字节处
如果编写的程序只在本地机器上运行,那么是不需要考虑大小端转换的问题的;但是到了网络通信时,是两台主机在进行进程间通信了,那么这两台主机采用的存储方式可能不一样,比如大端机器传数据给小端机器,那么小端机器解析出来的数据就和大端机器是不一样的
所以我们解决上面的问题,为此:TCP/IP 协议 规定,网络数据流都要采用大端字节序:
- 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出。
- 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存。
- 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。
- TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。
- 不管这台主机是大端机还是小端机,都会按照这个TCP/IP规定的网络字节序来发送/接收数据。
- 如果当前发送主机是小端,就需要先将数据转成大端,否则就忽略,直接发送即可。
注意:所有的大小端的转化工作由操作系统来完成,因为该操作属于通信细节,不过也有部分的数据需要我们自行进行处理,比如IP的端口号
同时,为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换:
#include<arpa/inet.h>uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntonl(uint32_t netlong);
uint16_t ntons(uint16_t netshort);
- h表示host,n表示network,l表示32位长整数,s表示16位短整数。
- 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
- 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
- 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
四,socket编程接口
4.1 socket常见API
我们会后面写代码常用到的,一共是五个:
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);// 开始监听socket (TCP, 服务器)int listen(int socket, int backlog);// 接收请求 (TCP, 服务器)int accept(int socket, struct sockaddr* address, socklen_t* address_len);// 建立连接 (TCP, 客户端)int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
4.2 sockaddr结构
可以发现,上面的每个接口的参数都有一个结构体指针 struct sockaddr* addr,下面详细介绍一下:
套接字有三种:
- 1,域间套接字编程:套接字不仅支持跨网络的进程间通信,也支持本地的进程间通信,用的就是这个
- 2,原始套接字编程:通常用来编写一些网络工具,比如监测,抓包等
- 3,网络套接字编程:重点使用传输层,通过TCP和UDP实现用户间的网络通信
所以最开始的套接字结构体提供了两种:
- sockaddr_un:用于本地
- sockaddr_in:用于跨网络
套接字种类不同,就有不同的应用场景,但是网络接口的设计者不想搞三套,计划将网络接口统一抽象化;而网络接口要想统一,那么接口的参数类型必须一致,所以就设计了sockaddr这个结构体:
- 之后在传参数的时候只要传sockaddr这一个就可以了,在设置参数之前就可以往这个结构体添加字段,这点下一篇简单Udp和程序的代码中会具体表现
- 如上图,在调用socket API 的那些接口时,这些API就可以提取 sockaddr 内部的头16字节进行识别,进而得出我们是要进行网络通信还是本地通信,执行对应的操作,完成接口的统一
- 注意:实际在进行网络通信时,定义的还是 sockaddr_in 这样的结构体,只是在传参的时候将该结构体的地址类型强制转换位 sockaddr* 罢了
问题:为啥不用C语言的万能参数 void* 来代替struct sockaddr* 类型呢?
解答:最简单的原因就是,设计网络接口时,C语言还不支持void*传参,而在后面C语言支持void*之后,也很难改回来了,因为这些接口都是系统接口,而系统接口是上层软件接口的基石,所以系统接口不是想改就改的,所以现在的网络接口依旧保留了sockaddr
相关文章:

计算机网络(二) —— 网络编程套接字
目录 一,认识端口号 1.1 背景 1.2 端口号是什么 1.3 三个问题 二,认识Tcp协议和Udp协议 三,网络字节序 四,socket编程接口 4.1 socket常见API 4.2 sockaddr结构 一,认识端口号 1.1 背景 问题:在进…...

二百五十九、Java——采集Kafka数据,解析成一条条数据,写入另一Kafka中(一般JSON)
一、目的 由于部分数据类型频率为1s,从而数据规模特别大,因此完整的JSON放在Hive中解析起来,尤其是在单机环境下,效率特别慢,无法满足业务需求。 而Flume的拦截器并不能很好的转换数据,因为只能采用Java方…...

Qt项目使用Inno Setup打包(关于打包中文乱码的解决)
关于打包好的文件乱码解决方法 打包好的文件中文乱码,就是编码格式出现了问题,更改一下中文脚本编码格式,在官网Inno Setup Translations下载好中文脚本 点击下载,然后另存为 得到ChineseSimplified.isl.txt文件后&#…...

HTML和HTML5有什么区别
HTML(超文本标记语言)是构建网页的基础,而HTML5是HTML的最新版本。虽然HTML和HTML5在许多方面相似,但HTML5引入了许多新的特性和改进,使得网页开发更加高效和功能丰富。 一、HTML概述 HTML,即超文本标记语…...

Collections
Collections 是 Java 中的一个实用工具类,提供了一系列静态方法来操作集合。以下是其详细介绍: 前置知识 在 Java 中,可变参数(Varargs)允许方法接受可变数量的参数。使用可变参数时,可以传递任意数量的参…...

fastreport打印trichedit分页问题的解决
用fastreport来打印richedit里面的内容。刚开始放一个frxrichview组件到报表上,然后在 var str: TMemoryStream; begin begin str: TMemoryStream.Create; CurrRichRecord.richedit.Lines.SaveToStream(str); str.Position: 0; tfrxRichview(fr…...

【MeterSphere】vnc连接不上selenium-chrome容器
目录 一、现象 二、查看配置文件 docker-compose-seleniarm.yml 三、处理 3.1 删除上图当中的三行 3.2 msctl reload 3.3 重新连接 前言:使用vnc连不上ms的selenium-chrome容器,看不到里面运行情况,以前其实可以,后来不行…...

mysql explain分析
目录 思维导图 id select_type SIMPLE PRIMARY SUBQUERY DEPENDENT SUBQUREY UNCACHEABLE SUBQUREY: UNION UNION RESULT DERIVED MATERIALIZED table partitions type ALL index range ref eq_ref const system possible_keys keys key_l…...

[论文笔记]Circle Loss: A Unified Perspective of Pair Similarity Optimization
引言 为了理解CoSENT的loss,今天来读一下Circle Loss: A Unified Perspective of Pair Similarity Optimization。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 这篇论文从对深度特征学习的成对相似度优化角度出发,旨在最大化同类之间…...

Windows .NET8 实现 远程一键部署,几秒完成发布,提高效率 - CICD
1. 前言 场景 (工作环境 一键部署 到 远端服务器 [阿里云]) CICD 基本步骤回顾 https://blog.csdn.net/CsethCRM/article/details/141604638 2. 环境准备 服务器端IP:106.15.74.25(阿里云服务器) 客户端࿱…...

echarts 水平柱图 科技风
var category [{ name: "管控", value: 2500 }, { name: "集中式", value: 8000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 } ]; // 类别 var total 10000; // 数据…...

标准IO与系统IO
概念区别 标准IO:(libc提供) fopen fread fwrite 系统IO:(linux系统提供) open read write 操作效率 因为内存与磁盘的执行效率不同 系统IO: 把数据从内存直接写到磁盘上 标准IOÿ…...

【conda】Conda 环境迁移指南:如何更改 envs_dirs 和 pkgs_dirs 以及跨盘迁移
目录 迁移概述一、conda 配置文件1.1 安装 Conda 后的默认目录设置1.2 查看当前 .condarc 配置 二、更改 Conda 的 envs_dirs 和 pkgs_dirs 设置2.1 使用 conda config 命令Windows 和 Linux 系统 2.2 手动编辑 .condarc 文件Windows 系统Linux 系统 2.3 验证设置 三、迁移 Con…...

脏页写入磁盘的过程详解
脏页写入磁盘的过程 一、引言 在数据库系统中,脏页是指那些被修改过但还未写入磁盘的数据页。为了保证数据的一致性和持久性,数据库系统需要在适当的时候将脏页写入磁盘。了解脏页写入磁盘的过程对于理解数据库的内部工作机制和优化性能至关重要。 二、触发脏页写入的条件…...

数据结构——单链表实现和注释浅解
关于单链表的基础部分增删查改的实现和一点理解,写在注释里~ SList.h #pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h>//定义节点的结构 //数据 指向下一个节点的指针 typedef int SLTDataType;typedef struct SListNo…...

滑动窗口系列(同向双指针)/9.7
新的解题思路 一、三数之和的多种可能 给定一个整数数组 arr ,以及一个整数 target 作为目标值,返回满足 i < j < k 且 arr[i] arr[j] arr[k] target 的元组 i, j, k 的数量。 由于结果会非常大,请返回 109 7 的模。 输入&…...

C# 窗体中Control以及Invalidate,Update,Refresh三种重绘方法的区别
在 C# 中,Control 类是 Windows Forms 应用程序中所有控件的基类。它提供了控件的基本功能和属性,这些功能和属性被所有继承自 Control 类的子类所共享。这意味着 Control 类是构建 Windows Forms 应用程序中用户界面元素的基础。 以下是 Control 类的一…...

缓存类型以及读写策略
缓存(Cache)是一种高效的数据存储技术,旨在提高数据访问速度。 它将频繁访问或最近使用的数据临时存储在更快速但较小的存储介质(如内存)中,以减少从较慢的存储设备(如硬盘或远程服务器&#x…...

自动驾驶---Motion Planning之轨迹拼接
1 背景 笔者在之前的专栏中已经详细讲解了自动驾驶Planning模块的内容:包括行车的Behavior Planning和Motion Planning,以及低速记忆泊车的Planning。 本篇博客主要聊一聊Motion Planning中轨迹拼接的相关内容。从网络上各大品牌的车主拍摄的智驾视频来看…...

没资料的屏幕怎么点亮?思路分享
这次尝试调通一个没资料的屏幕,型号是HYT13264,这个是淘宝上面的老王2.9元屏,成色很好但是长期库存没有资料和代码能点亮,仅仅只有一个引脚定义。这里我使用Arduino Nano作为控制器尝试点亮这个模块。 首先,已知别人找…...

通信工程学习:什么是FEC前向纠错
FEC:前向纠错 FEC(Forward Error Correction,前向纠错)是一种增加数据通信可信度的技术,广泛应用于计算机网络、无线通信、卫星通信等多种数据传输场景中。其基本原理和特点可以归纳如下: 一、FEC前向纠错…...

【机器人工具箱Robotics Toolbox开发笔记(二十)】机器人工具箱SerialLink I类函数参数说明
机器人工具箱中的SerialLink表示串联机器人型机器人的具体类。该类使用D-H参数描述,每个关节一组。SerialLink I类包含的参数如表1所示。 表1 SerialLink I类参数 参 数 意 义 参 数 意 义 plot 显示机器人的图形表示 jacobn 工具坐标系中的雅可比矩阵 plot3D 显示机…...
单调栈的实现
这是C算法基础-数据结构专栏的第二十四篇文章,专栏详情请见此处。 引入 单调栈就是满足单调性的栈结构,它最经典的应用就是给定一个序列,找出每个数左边离它最近的比它大/小的数。 下面我们就来讲单调栈的实现。 定义 单调栈就是满足单调性…...

ffmpeg的安装和使用教程
在Linux上安装和使用FFmpeg可以方便地完成音视频的编码、解码、转码等操作。以下是详细的安装和使用教程。 安装FFmpeg FFmpeg的安装方法会因为不同的Linux发行版有所不同。下面是几种常见的安装方法: Ubuntu/Debian 打开终端,更新包列表并安装FFmpe…...

从计组中从重温C中浮点数表示及C程序翻译过程
目录 移码编辑 传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 例子: 编辑 浮点数取的过程 C程序翻译过程 移码 传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 根据国际标准IEEE࿰…...

MySQL常用函数(总结)详细版
1. 字符串函数 CONCAT(str1, str2, ...):将多个字符串连接成一个字符串。 SELECT CONCAT(Hello, , World); LENGTH(str):返回字符串的长度(字节数)。 SELECT LENGTH(Hello); SUBSTRING(str, pos, len):从字符串 …...

学习记录——day41 C++ 类的静态成员 static
静态成员,是类中不依赖于类对象而独立存在的成员变量,但仍然属于类,是成员的一种 静态成员的空间分配发生在出现编译阶段,不占用类的空间 静态成员分为,静态成员变量和静态成员函数 静态成员变量 1、相关概念 1&…...

JVM - Java内存区域
文章目录 目录 文章目录 运行时数据区域 程序计数器 栈 Java虚拟机栈 本地方法栈 栈帧的组成 局部变量表 操作数栈 帧数据 堆 方法区 直接内存 总结 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这些区…...

本地电脑交叉编译ffmpeg 到 windows on arm64
本地电脑交叉编译ffmpeg 到 windows on arm64 我这里有编译好的win on arm 的 ffmpeg : https://github.com/wmx-github/ffmpeg-wos-arm64-build 使用 llvm-mingw 工具链 https://github.com/mstorsjo/llvm-mingw/releases 前缀 aarch64-w64-mingw32- 这个库是ubuntu 交叉编译…...

使用 @NotEmpty、@NotBlank、@NotNull 注解进行参数校验
使用 NotEmpty、NotBlank、NotNull 注解进行参数校验 一、前言二、依赖三、使用 NotEmpty、NotBlank、NotNull 注解进行参数校验1. NotNull2. NotEmpty3. NotBlank4. 区别与适用场景 四、实践中的应用五、总结 一、前言 在 Java 开发中,参数校验是确保数据一致性和…...