Socket 编程预备

目录

理解源 IP 地址和目的 IP 地址

认识端口号 

端口号范围划分 

理解 "端口号" 和 "进程 ID" 

理解源端口号和目的端口号 

理解 socket 

传输层的典型代表

认识 TCP 协议 

认识 UDP 协议 

 网络字节序

socket 编程接口 

socket 常见 API

sockaddr 结构 


理解源 IP 地址和目的 IP 地址

IP 在网络中,用来标识主机的唯一性

但是这里要思考一个问题:数据传输到主机是目的吗?不是的。因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览?

但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?通过启动的 qq,迅雷,浏览器。

而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。

所以:数据传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程, 才是目的。

但是系统中,同时会存在非常多的进程,当数据到达目标主机之后,怎么转发给目标进程?这就要在网络的背景下,在系统中,标识主机的唯一性。 

认识端口号 

端口号(port)是传输层协议的内容.

(为了能在任意一个主机内部,标识某一个进程的唯一性,在计算机网络里引入了端口号)

1.  端口号是一个 2 字节 16 位的整数;(0到2^16-1)

2.  端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;

3.  IP 地址 + 端口号能够标识网络上的某一台主机的某一个进程;

4.  一个端口号只能被一个进程占用.

端口号范围划分 

1.  0 - 1023: 知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的端口号都是固定的. (就像打110就知道报警,打120知道医院救护车)

2.  1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的.

理解 "端口号" 和 "进程 ID" 

之前在系统编程的时候, 知道 pid 表示唯一一个进程; 此处我们的端口号也是唯一表示一个进程. 那么这两者之间是怎样的关系?

1.   一个进程可以绑定多个端口号; 但是一个端口号不能被多个进程绑定;

2.  进程 ID 属于系统概念,技术上也具有唯一性,确实可以用来标识唯一的一个进程,但是这样做,会让系统进程管理和网络强耦合(例如pid变了那么port也要变,进程每次启动pid都会变),实际设计的时候,并没有选择这样做。主要是让系统与网络解耦;

3.  系统中所有进程都有pid,但并不是所有进程都想网络通信,只有少量的进程需要通信的才需要端口号。所以有端口号的才是想网络通信的。

理解源端口号和目的端口号 

传输层协议(TCP 和 UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号. 就是在描述 "数据是谁发的, 要发给谁";源端口号和目的端口号在同一个报文中,它们是 TCP 或 UDP 数据报文头部的一部分

理解 socket 

1.  综上,IP 地址用来标识互联网中唯一的一台主机,port 用来标识该主机上唯一的一个网络进程;

 2.  IP+Port 就能表示互联网中唯一的一个进程 ;

3.  所以,通信的时候,本质是两个互联网进程代表人来进行通信,{srcIp, srcPort,dstIp,dstPort}这样的 4 元组就能标识互联网中唯二的两个进程 ;

4.  所以,网络通信的本质,也是进程间通信 ;

5.  我们把 ip+port 叫做套接字 socket;

传输层的典型代表

此处先做了解;

传输层是属于内核的(传输层和网络层),那么我们要通过网络协议栈进行通信,必定调用的是传输层提供的系统调用,来进行的网络通信。

认识 TCP 协议 

先对 TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识;

1.  传输层协议 

2.  有连接 

3.  可靠传输 

4.  面向字节流

认识 UDP 协议 

对 UDP(User Datagram Protocol 用户数据报协议)有一个直观的认识;

1.  传输层协议 

2.  无连接 

3.  不可靠传输 

4.  面向数据报

 网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分(大小端是数据的存储方式;), 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?

发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出; 

接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存; 

因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.

TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址高字节.

不管这台主机是大端机还是小端机, 都会按照这个 TCP/IP 规定的网络字节序来发送/接收数据; 

如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可;

为使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。 

socket 编程接口 

socket 常见 API

API(Application Programming Interface,应用程序编程接口)是一组定义不同软件组件之间交互规则的接口。简单来说,它是一种使得不同的软件系统、应用程序能够相互通信、共享数据和功能的方式。

C

// 创建 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);

sockaddr 结构 

socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、IPv6,以及后面的 UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同.

1.   IPv4 和 IPv6 的地址格式定义在 netinet/in.h 中,IPv4 地址用 sockaddr_in 结构体表示,包括 16 位地址类型, 16 位端口号和 32 位 IP 地址. 

2.  IPv4、IPv6 地址类型分别定义为常数 AF_INET、AF_INET6. 这样,只要取得某种 sockaddr 结构体的首地址,不需要知道具体是哪种类型的 sockaddr 结构体,就可以根据地址类型字段确定结构体中的内容. 

3.  socket API 可以都用 struct sockaddr *类型表示, 在使用的时候需要强制转化成 sockaddr_in; 这样的好处是程序的通用性, 可以接收 IPv4, IPv6, 以及 UNIX Domain Socket 各种类型的 sockaddr 结构体指针做为参数;

sockaddr 结构 

sockaddr_in 结构 

虽然 socket api 的接口是 sockaddr, 但是我们真正在基于 IPv4 编程时, 使用的数据结 构是 sockaddr_in; 这个结构里主要有三部分信息: 地址类型, 端口号, IP 地址.

in_addr 结构 

in_addr 用来表示一个 IPv4 的 IP 地址. 其实就是一个 32 位的整数;

 Socket编程UDP

UDP比较简单,建立好后就可以连接了。 

UDP 网络编程

V1 版本 - echo server

简单的回显服务器和客户端代码 备注: 代码中会用到地址转换函数

socket函数:

#include <sys/types.h>
 #include <sys/socket.h>

 int socket(int domain, int type, int protocol);

验证文件描述符_socket是3;

bind 绑定端口号:一个用于将一个套接字(socket)与一个特定的地址绑定的系统调用。在网络编程中,通常用于在服务端应用中指定服务器的地址和端口。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);


bind() 函数通常用于服务端在使用 UDP 或 TCP 协议时,绑定到一个特定的端口和地址。客户端则不需要调用 bind(),因为它通常会让操作系统自动为它选择一个可用端口。

 ip字符串转化网络字节序列

验证绑定成功: 

显示当前系统的网络连接、套接字以及相关信息,查看udp信息:

如果信息不全可以试试sudo,用管理员权限

recvfron函数:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

recvfrom 是一个系统调用,通常用于在网络编程中接收数据。它属于 套接字(socket)编程 的一部分,特别是用于 UDP 套接字(虽然它也可以用于其他协议)。recvfrom 函数能够接收来自远程主机的消息,并且除了接收到的数据,还可以获取消息的源地址和端口。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

17. Threejs案例-Three.js创建多个立方体

17. Threejs案例-Three.js创建多个立方体 实现效果 知识点 WebGLRenderer (WebGL渲染器) WebGLRenderer 是 Three.js 中用于渲染 WebGL 场景的核心类。它负责将场景中的对象渲染到画布上。 构造器 new THREE.WebGLRenderer(parameters) 参数类型描述parametersObject可选…

实例教程:BBDB为AHRS算法开发提供完善的支撑环境(下)

4. BBDB基础上为算法实现提供支撑方式二&#xff1a;算法层实现 第2节内容当中讲述在应用层实现AHRS的步骤&#xff0c;这种方法优点在于实现方法比较简单明了。但是缺点在于程序代码的组织算不上很好&#xff0c;AHRS算法代码与PH47框架代码间存在一定的耦合度&#xff0c;会…

Android开发,使用ViewPager2实现自动轮播图

文章目录 1. build.gradle添加依赖&#xff1a;2. AndroidManifest.xml中添加网络访问权限3. 编写 布局文件4. 编写Banner适配器5. 自定义Banner视图6. 定义圆点指示器的drawable资源7. 在需要使用轮播图中的Activity中使用8. 运行效果图9. 视频教程 在Android项目程序设计中&a…

企业网双核心交换机实现冗余和负载均衡(MSTP+VRRP)

MSTP&#xff08;多生成树协议&#xff09; 通过创建多个VLAN实例&#xff0c;将原有的STP、RSTP升级&#xff0c;避免单一VLAN阻塞后导致带宽的浪费&#xff0c;通过将VLAN数据与实例绑定&#xff0c;有效提升网络速率。 VRRP&#xff08;虚拟路由冗余协议&#xff09; 用…

Socket编程-tcp

1. 前言 在tcp套接字编程这里&#xff0c;我们将完成两份代码&#xff0c;一份是基于tcp实现普通的对话&#xff0c;另一份加上业务&#xff0c;client输入要执行的命令&#xff0c;server将执行结果返回给client 2. tcp_echo_server 与udp类似&#xff0c;前两步&#xff1…

15分钟训练数字人MimicTalk

只需15分钟&#xff0c;就能训练高质量&#xff0c;个性化数字人大模型。由浙江大学与字节跳动联合推出MimicTalk算法&#xff0c;目前已开源。 在外表和说话风格上和真人相似。将通用3D数字人大模型适应到单个目标人&#xff0c;采用动静结合的高效微调方案&#xff0…

【kettle】mysql数据抽取至kafka/消费kafka数据存入mysql

目录 一、mysql数据抽取至kafka1、表输入2、json output3、kafka producer4、启动转换&#xff0c;查看是否可以消费 二、消费kafka数据存入mysql1、Kafka consumer2、Get records from stream3、字段选择4、JSON input5、表输出 一、mysql数据抽取至kafka 1、表输入 点击新建…

在 MacOS 上为 LM Studio 更换镜像源

在 MacOS 之中使用 LM Studio 部署本地 LLM时&#xff0c;用户可能会遇到无法下载模型的问题。 一般的解决方法是在 huggingface.co 或者国内的镜像站 hf-mirror.com 的项目介绍卡页面下载模型后拖入 LM Studio 的模型文件夹。这样无法利用 LM Studio 本身的搜索功能。 本文将…

vue中.sync修饰符的用法

一、什么是.sync修饰符 在Vue.js中&#xff0c;.sync 修饰符用于创建一个双向绑定的 prop。它使子组件能够更新父组件的 prop 值&#xff0c;实现父子组件之间的双向数据同步。具体来说&#xff0c;.sync 修饰符主要有以下几个功能&#xff1a; 简化双向绑定&#xff1a; 使用…

【附源码】基于环信鸿蒙IM SDK实现一个聊天Demo

项目背景 本项目基于环信IM 鸿蒙SDK 打造的鸿蒙IM Demo&#xff0c;完全适配HarmonyOS NEXT系统&#xff0c;实现了发送消息&#xff0c;添加好友等基础功能。代码开源&#xff0c;功能简洁&#xff0c;如果您有类似开发需求可以参考。 源码地址&#xff1a;https://github.c…

SHELL----正则表达式

一、文本搜索工具——grep grep -参数 条件 文件名 其中参数有以下&#xff1a; -i 忽略大小写 -c 统计匹配的行数 -v 取反&#xff0c;不显示匹配的行 -w 匹配单词 -E 等价于 egrep &#xff0c;即启用扩展正则表达式 -n 显示行号 -rl 将指定目录内的文件打…

Can‘t find variable: token(token is not defined)

文章目录 例子 1&#xff1a;使用 var例子 2&#xff1a;使用 let 或 const例子 3&#xff1a;异步操作你的代码中的情况 Cant find variable: tokentoken is not defined源代码 // index.jsPage({data: {products:[],cardLayout: grid, // 默认卡片布局为网格模式isGrid: tr…

【AI系统】GhostNet 系列

GhostNet 系列 本文主要会介绍 GhostNet 系列网络&#xff0c;在本文中会给大家带来卷积结构的改进方面的轻量化&#xff0c;以及与注意力(self-attention)模块的进行结合&#xff0c;部署更高效&#xff0c;更适合移动计算的 GhostNetV2。让读者更清楚的区别 V2 与 V1 之间的…

YOLOv8改进,YOLOv8引入CARAFE轻量级通用上采样算子,助力模型涨点

摘要 CARAFE模块的设计目的是在不增加计算复杂度的情况下,提升特征图的质量,特别是在视频超分辨率任务中,提升图像质量和细节。CARAFE结合了上下文感知机制和聚合特征的能力,通过动态的上下文注意力机制来提升细节恢复的效果。 理论介绍 传统的卷积操作通常依赖于局部区域…

大型制造企业IT蓝图、信息化系统技术架构规划与实施路线方案

关注 获取ppt​​​​​​全文&#xff0c;请关注作者

HTTP 长连接(HTTP Persistent Connection)简介

HTTP长连接怎么看&#xff1f; HTTP 长连接&#xff08;HTTP Persistent Connection&#xff09;简介 HTTP 长连接&#xff08;Persistent Connection&#xff09;是 HTTP/1.1 的一个重要特性&#xff0c;它允许在一个 TCP 连接上发送多个 HTTP 请求和响应&#xff0c;而无需为…

001集—— 创建一个WPF项目 ——WPF应用程序入门 C#

本例为一个WPF应用&#xff08;.NET FrameWork&#xff09;。 首先创建一个项目 双击xaml文件 双击xaml文件进入如下界面&#xff0c;开始编写代码。 效果如下&#xff1a; 付代码&#xff1a; <Window x:Class"WpfDemoFW.MainWindow"xmlns"http://schema…

微信小程序配置less并使用

1.在VScode中下载Less插件 2.在微信小程序中依次点击如下按钮 选择 从已解压的扩展文件夹安装… 3.选中刚在vscode中下载安装的插件文件 如果没有修改过插件的安装目录&#xff0c;一般是在c盘下C:\用户\用户名.vscode\extensions\mrcrowl.easy-less-2.0.2 我的路径是&#xf…

Vue网页屏保

Vue网页屏保 在vue项目中&#xff0c;如果项目长时间未操作需要弹出屏幕保护程序&#xff0c;以下为网页屏保效果&#xff0c;看板内容为连接的资源。 屏保组件 <template><div v-if"isActive" class"screensaver" click"disableScreens…

【SpringBoot】使用IDEA创建SpringBoot项目

1、使用SpringBoot脚手架创建 我们使用SpringBoot的脚手架Spring Initializr创建&#xff0c;如图所示&#xff1a; 2、选择SpringBoot版本 最开始做项目时候&#xff0c;组长说创建一个 springboot 2.5.4 的项目&#xff0c;mysql使用 5.6.X &#xff0c;maven使用是3.6.X…