Linux系统编程--网络编程

一、OSI网络七层模型

OSI模型将整个网络通信过程分解为七个层次,每个层次都为网络通信提供了特定的功能。以下是OSI模型的七个层次,从上到下依次是:

  1. 应用层(Application Layer):为应用软件提供网络服务,如HTTP、FTP、SMTP等协议,处理网络应用程序的具体功能。

  2. 表示层(Presentation Layer):确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取,负责数据格式转换、数据加密解密等。

  3. 会话层(Session Layer):建立、管理和终止应用程序之间的会话,提供数据交换定界和同步功能,包括建立检查点和恢复方案。

  4. 传输层(Transport Layer):负责主机中两个进程的对话控制,如TCP(传输控制协议)和UDP(用户数据报协议),处理数据包的顺序、错误校验、流量控制等。

  5. 网络层(Network Layer):负责数据包从源到宿的传递和路由选择,如IP(互联网协议)。

  6. 数据链路层(Data Link Layer):传输有地址的帧以及错误检测功能,如以太网协议。

  7. 物理层(Physical Layer):处理通过物理设备传输数据的技术细节,如网线、光纤、无线电波等。

  8. OSI模型的每一层都为它的上层提供服务,同时依赖于它的下层。这种分层的设计使得网络通信更加模块化,便于理解和设计复杂的网络系统。在实际应用中,TCP/IP模型是更为广泛使用的网络模型,它简化了层次结构,但基本原理与OSI模型相似。

后来人们对 OSI 进行了简化,合并了一些层,最终只保留了 4 层,从下到上分别是接口层、网络层、传输 层和应用层,这就是大名鼎鼎的 TCP/IP 模型。

本次讲的是spcket编程,是站在传输层的基础上,可以使用TCP/UDP协议。

二、网络数据传输过程

平常使用的软件都是通过应用层来访问网络,程序产生的数据会一层层地往下传输,直到最后的网络接口层,就通过网线发送到互联网上去了。

数据向下:原始数据每通过一层,就会多一层协议的包装,通过四层,原始数据变成包装数据。

数据向上:包装数据每通过一层,就会少一层协议的包装,通过四层,包装数据被完全拆解成原始数据。

1.TCP通信协议

TCP 是面向连接的传输协议,可靠性传输,建立连接时要经过三次握手,断开连接时要经过四次挥手,中间 传输数据时也要回复 ACK 包确认,多种机制保证了数据能够正确到达,不会丢失或出错。

1、TCP 的 3 次握手过程 1、客户端发送 TCP 连接请求 客户端会随机一个初始序列号 seq=x(client_isn),设置 SYN=1,表示这是 SYN 握手报文。然后 就 可以把这个 SYN 报文发送给服务端了,表示向服务端发起连接,之后客户端处于同步已发送状态。

2、服务端发送针对 TCP 连接请求的确认,服务端收到客户端的 SYN 报文后,也随机一个初始序列号 (server_isn)(seq=y),设置 ack=x+1, 表示收到了客户端的 x 之前的数据,希望客户端下次发送的数据从 x+1 开始。设置 SYN=1 和 ACK=1。表示这是一个 SYN 握手和 ACK 确认应答报文。 最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于同步已接收状态。

3、客户端发送确认的确认 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,将 ACK 置为 1 ,表示这是一个 应答报文 ack=y+1 ,表示收到了服务器的 y 之前的数据,希望服务器下次发送的数据从 y+1 开始。最 后把报文发送给服务端,这次报文可以携带数据,之后客户端处于连接已建立 状态。服务器收到客户 端的应答报文后,也进入连接已建立状态 通过这样的三次握手过程,TCP 能够确保双方能够收到对方的请求和回应,并且双方都知道彼此的初始 序列号和确认号。这样建立起来的连接可以提供可靠的数据传输和顺序控制。 ACK:确认序号有效。 SYN:发起一个新连接。

CLOSED:不在连接状态(这是为方便描述假想的状态,实际不存在)

LISTEN:等待从任何远端 TCP 和端口的连接请求。

SYN_SENT:发送完一个连接请求后等待一个匹配的连接请求。

syn_sent SYN_RCVD: 这个状态表示接受到了 SYN 报文,在正常情况下,这个状态是服务器端的 SOCKET 在建立 TCP 连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用 netstat 你是很难看到这种状态的,除非你特 意写了一个客户端测试程序,故意将三次 TCP 握手过程中最后一个 ACK 报文不予发送。因此这种状态时,当收到客户端的 ACK 报文后,它会进入到 ESTABLISHED 状态 ESTABLISHED:表示一个打开的连接,接收到的数据可以被投递给用户。连接的数据传输阶段的正常状态

为什么是三次握手,为什么不是两次或者四次?

主要原因:防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误 如果采用两次握手会出现以下情况: 客户端向服务器端发送的请求报文由于网络等原因滞留,未能发送到服务器端,此时连接请求报文失效, 客户端会再次向服务器端发送请求报文,之后与服务器端建立连接,当连接释放后,由于网络通畅了,第一次客 户端发送的请求报文又突然到达了服务器端,这条请求报文本该失效了,但此时服务器端误认为客户端又发送了 一次连接请求,两次握手建立好连接,此时客户端忽略服务器端发来的确认,也不发送数据,造成不必要的错误 和网络资源的浪费。 如果采用三次握手的话,就算那条失效的报文发送到服务器端,服务器端确认并向客户端发送报文,但此时 客户端不会发出确认,由于客户端没有确认,由于服务器端没有接收到确认,就会知道客户端没有请求连接。

为什么不是四次?如果三次就能够确定正常连接,就没有必要在进行确认,来浪费资源了

2.UDP通信协议

UDP 是非面向连接的传输协议,没有建立连接和断开连接的过程,它只是简单地把数据丢到网络中,也不 需要 ACK 包确认。在数据传输过程中延迟小、数据传输效率高。 当强调传输性能而不是传输的完整性时,如:音频和多媒体应用,UDP 是最好的选择。

总结:

短链接,不连接通信 

相对来说没有 TCP 那么稳定

有可能丢失相应数据  

它的发送速度相对TCP来说比较快

3.网络编程的 IP 地址

windows 下:ipconfig

Linux 下:ifconfig

1、ipv4地址是32(bit)地址数据、现在发展到ipv6

2、ip由网络号和主机号组成

3、子网掩码:255.255.255.0

4、端口

端口(Port)是一个逻辑概念,用于区分不同的服务或进程。端口号与IP地址一起工作,帮助网络协议(如TCP/IP)确定数据应该被送往网络中哪一台主机的哪个具体服务。端口号是16位的数字,范围从0到65535。

端口号分为几个范围:

  1. 知名端口(Well-Known Ports):范围从0到1023,通常被系统或者常见服务和应用程序使用。例如,HTTP服务通常使用端口80,HTTPS服务使用端口443,而FTP服务使用端口21。

  2. 注册端口(Registered Ports):范围从1024到49151,用于用户或应用程序。这些端口号用于运行用户开发的服务或应用程序,但它们不像知名端口那样广为人知。

  3. 动态或私有端口(Dynamic or Private Ports):范围从49152到65535,通常不由任何服务固定使用,而是由各种应用程序在需要时临时使用。

端口的作用包括:

  • 区分服务:不同的网络服务监听不同的端口,例如,Web服务器监听端口80或443,而电子邮件服务器可能监听端口25(SMTP)或110(POP3)。

  • 进程间通信:在一台主机上,不同的进程可以通过不同的端口号进行网络通信。

  • 网络配置:端口号也用于配置网络服务,如防火墙和路由器规则,允许或阻止对特定端口的访问。

  • 安全性:通过限制对某些端口的访问,可以提高网络安全性。例如,关闭不常用或不必要的端口可以减少潜在的安全风险。

在网络编程中,端口的使用通常涉及以下步骤:

  • 绑定(Binding):一个网络应用程序在启动时会绑定到一个特定的端口号,这样它就可以监听进入该端口的网络请求。

  • 监听(Listening):绑定到端口的应用程序会进入监听状态,等待网络请求的到来。

  • 连接(Connecting):当客户端程序需要与服务端通信时,它会指定服务器的IP地址和端口号来建立连接。

  • 通信:一旦连接建立,客户端和服务器就可以通过这个端口进行数据传输。

端口的使用对于网络通信至关重要,它们使得复杂的网络环境能够有序地运行。

5.TCP编程协议框架

6.TCP 服务端编写流程

1、创建套接字:sockeet

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

参数: domain: 网域

        AF_INET :IPv4

        AF_INET6 :IPv6

        AF_UNIX :本地通讯

type:选择传输协议 tcp /udp

        SOCK_STREAM ;tcp

        SOCK_DGRAM : udp

protocol: 基本废弃,一般赋 0

返回值:

        成功返回描述网络套接字 sockfd,失败返回-1

举例:

        创建描述网络的套接字:

         int sfd = socket(AF_INET,SOCK_STREAM,0)

2、绑定:bind

绑定一个端口号和 IP 地址,使套接口与指定的端口号和 IP 地址相关

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)

参数:sockfd 为前面 socket 的返回值,描述网络的套接字

        my_addr:封装 ip 地址和端口号 struct sockaddr //一般很少用

struct sockaddr //一般很少用
{unsigned short int sa_family; // AF_INET。char sa_data[14]; //IP 和端口
};
#include<netinet/in.h>
struct sockaddr_in //常用的结构体
{unsigned short int sin_family; //AF_INETuint16_t sin_port; //使用的 port 编号struct in_addr sin_addr; // IP 地址unsigned char sin_zero[8]; //未使用
};端口:10000-65535
12345
htons h-host to n-net s:short
转化:uint32_t htonl(uint32_t hostlong);//本函数将一个 32 位数从主机字节顺序转换成            无符号长整型网络字节
顺序:
uint16_t htons(uint16_t hostshort);//将一个无符号短整型的主机数值转换为网络字节顺序
uint32_t ntohl(uint32_t netlong);//将一个无符号长整形数从网络字节顺序转换为主机字节顺序。
uint16_t ntohs(uint16_t netshort);//将一个 16 位数由网络字节顺序转换为主机字节顺序。
IP 的填写方式:
struct in_addr
{uint32_t s_addr; //=inet_addr("192.168.1.22");
};
addrlen:第二个参数大小
返回值:成功则返回 0,失败返回-1
举例:
#define PORT 33333
#define IP "192.168.110.123" struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(PORT);
ser_addr.sin_addr.s_addr = inet_addr(IP);
inet_aton(“192.168.1.22”,&ser_addr.sin_addr);
bind(sfd,(struct sockaddr)&ser_addr,sizeof(ser_addr));

3、监听:listen

设置允许的最大连接数(瞬时处理的阈值),listen 函数

使服务器的这个端口和 IP 处于监听状态,等待网络中某一客户机的连接请求。如果客户端有连接请求, 端口就会接受这个连接

int listen(int sockfd, int backlog);
参数sockfd 为前面 socket 的返回值,sfdbacklog 指定同时能处理的最大连接要求,通常为 10 或者 5。 最大值可设至 128(不是最多可以连接 128 个客户端,是一个瞬时处理的阈值)返回值:成功则返回 0,失败返回-1
例子:listen(sfd,10);

4、等待客户端连接:accept

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

参数 :

        sockfd 为前面 socket 的返回值,即 sfd

        addr:提供空间,用于接受客户端的 ip 地址和端口号

        addrlen:第二个参数大小

返回值: 返回新的套接字描述符,专门用于与建立的客户端通信 失败-1;

举例:

struct sockaddr_in cli_addr = {0};

socklen_t len = sizeof(cli_addr);

int cfd = accept(sfd,(struct sockaddr *)&cli_addr,&len)

5、write 和 read 进行通信

ssize_t send(int s, const void *buf, size_t len, int flags);

参数: s:通信套接字

        buf:要发送的数据缓冲区

        len: 数据长度

        flags:一般赋 0 .阻塞

返回值:成功返回真正发送的数据长度,失败-1

ssize_t recv(int s, void* buf,size_t len,int flags);

参数 s:通信的套接字

        buf:存放接收数据的缓冲区

        len: 数据长度

        flags:一般赋 0 .阻塞

返回值:成功返回真正接收的数据长度,失败-1

7.TCP 客户端编写流程

1、创建套接字:socket

#include <sys/socket.h>
int socket(int domain, int type, int protocol);

参数:

        domain: 网域

                AF_INET :IPv4

                AF_INET6 :IPv6

        type:选择传输协议 tcp /udp

                SOCK_STREAM ;tcp

                SOCK_DGRAM : udp

        protocol: 基本废弃,一般赋 0

返回值:成功返回套接字 fd,失败返回-1

2、connect : 连接
int connect(int sockfd, const struct sockaddr*serv_addr, socklen_t addrlen)

参数:sockfd 为前面 socket 的返回值,即 fd

        serv_addr 为结构体指针变量,存储着远程服务器的 IP 与端口号信息。

        addrlen 表示结构体变量的长度

返回值:成功则返回 0,失败返回-1

举例:
int fd = socket(AF_INET,SOCK_STREAM,0);
#define PORT 33333
#define IP "192.168.110.123" struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(PORT);
ser_addr.sin_addr.s_addr = inet_addr(IP);
connect(fd,(struct sockaddr *)&ser_addr,sizeof(ser_addr))
3、write 和 read 进行通信 或者 send 和 recv 进行通信

TCP 问题: 当服务器结束之后,再次运行会出现 bind 错误(地址被占用)

解决办法:

        int sfd = socket(AF_INET,SOCK_STREAM,0); 创建套接字之后,

用:

        int val = 1;

        setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));         setsockopt(sfd,SOL_SOCKET,SO_REUSEPORT,&val,sizeof(val));

7、单播、广播、多播

单播 -- 一对一 广播 -- 一对多 组播 -- 多

UDP 不像 TCP,无需在连接状态下交换数据,因此基于 UDP 的接收方和发送方也无需经过连接过程。也就 是说,不必调用 listen()和 accept()函数。UDP 中只有创建套接字的过程和数据交换的过程。不管是服务器端还是 客户端都只需要 1 个套接字

udp 具有广播功能,即一个发送方,多个接收方; 广播:处于局部网中的所有设备都可以接收到消息 比如:校园广播 广播的地址:网络号不变,主机号为 25

对一组特定的主机发送消息 比如:直播,多播(D 类),IP 地址分为:224.0.0.0~239.255.255.255

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

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

相关文章

Python数据可视化------地图

基础地图使用 # 地图基本演示 # 导包 from pyecharts.charts import Map from pyecharts.options import TitleOpts, VisualMapOpts# 准备地图对象 cmap Map() # 准备数据&#xff08;列表&#xff09; data [("北京市", 99), ("上海市", 199), ("…

【大模型】LLaMA-1 模型介绍

文章目录 一、背景介绍二、模型介绍2.1 模型结构2.2 模型超参数2.3 SwiGLU 三、代码分析3.1 模型结构代码3.2 FairScale库介绍 四、LLaMA家族模型4.1 Alpaca4.2 Vicuna4.3 Koala(考拉)4.4 Baize (白泽)4.5 Luotuo (骆驼&#xff0c;Chinese)4.6 其他 参考资料 LLaMA&#xff08…

微信小程序16: 组件通信

父子组件之间的通信 父子组件通信一共有三种方式 属性绑定 用于父组件向子组件的指定属性设置数据&#xff0c;仅能设置JSON兼容的数据 事件绑定 用于子组件向父组件传递数据&#xff0c;可以传递任意数据 获取组件实例 父组件还可以通过this.selectComponent()获取子组件的实…

vue 语法2

【5】条件渲染和列表渲染 &#xff08;1&#xff09;条件渲染v-if v-else-if v-else 条件渲染根据表达式的真假值来渲染不同的元素或组件。 v-if&#xff1a;当表达式的值为真时&#xff0c;渲染该元素或组件。 v-else-if&#xff1a;当前面的 v-if 或 v-else-if 的表达式为假…

【机器视觉】C# .NET 8 部署yolov9 onnx对象检测

这段代码展示了一个使用YOLOv9进行对象检测的简单测试框架。代码主体以及其功能分为以下几个关键部分&#xff1a; 创建测试图片数组 _testImages&#xff0c;它包含了图片文件名和对应的标签。使用 buildTests 方法来从给定的文件名中加载图片并调整尺寸&#xff0c;准备测试数…

linux数据备份与恢复

目录 前言 1、数据备份和恢复中的两个关键性指标 2、linux系统的定时任务 1&#xff09;本地定时任务crontab 在实验测试过程中&#xff0c;遇到多次crontab任务不执行问题 &#xff0c;总结下来主要有几个方面原因&#xff1a; 2)分布式定时任务系统Jenkins 3、备份存储…

如何用二维码实现现代仓库管理?(附详细实现过程)

简道云团队曾参与过近300企业的仓库管理软件的部署&#xff0c;要想知道如何实现用二维码管理仓库&#xff0c;首先要对整体流程有清晰的框架&#xff01; 1、产品数据的录入2、设计电子库存卡3、库存盘点单4、库存盘点报表 总结一下就是——数卡单表&#xff0c;四步实现&…

补一 继承的使用

继承的关键词为extends 模型为 public class 子类 extends 父类

中国热门高端dating约会交友软件有哪些?国内权威Dating App红黑排行榜推荐

在dating 软件刷了无数个男人后终于脱单啦&#xff0c;跟大家分享一些我的个人感受 1、二狗 颜值⭐️⭐️⭐️ 真实性 ⭐️⭐️⭐️⭐️⭐️ 用户质量⭐️⭐️⭐️⭐️ ⭕️优点&#xff1a;整体用户质量较高&#xff0c;用户集中在金融、互联网和体制内行业。用户需进行学历、…

速来get!多微信聚合聊天功能大揭秘!

随着网络时代的发展&#xff0c;微信成为了职场中不可或缺的沟通工具&#xff0c;很多人都有着多个微信号&#xff0c;而要想高效管理这些账号&#xff0c;那就少不了工具的帮忙。 通过微信管理系统&#xff0c;可以轻松实现多个微信号聚合聊天&#xff0c;提高沟通效率。 1、…

抓取Google时被屏蔽怎么办?如何避免?

在当今数字化时代&#xff0c;数据采集和网络爬取已成为许多企业和个人必不可少的业务活动。对于爬取搜索引擎数据&#xff0c;特别是Google&#xff0c;使用代理IP是常见的手段。然而&#xff0c;使用代理抓取Google并不是一件轻松的事情&#xff0c;有许多常见的误区可能会导…

顶顶通呼叫中心中间件电话黑名单系统介绍

黑名单 有显示成功和失败导入数&#xff0c;可以禁用也可以启用&#xff0c;如果禁用状态就是不使用这一组黑名单&#xff0c;多个号码核验就是验证号码存不存在。黑名单只有管理员和操作员可以配置&#xff0c;租户是看不到黑名单的。但是黑名单跟租户是互通的。 可以单个号码…

【智能算法应用】基于麻雀搜索算法的二维最大熵图像阈值分割

目录 1.算法原理2.数学模型3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】麻雀搜索算法&#xff08;SSA&#xff09;原理及实现 2.数学模型 最大熵法是由 Kapur 于 1985 年所提出的&#xff0c; 该方法的阈值选取标准取决于图像中最大化分 割的目标区域和背景区域…

STM32F1#1(入门了解)

一、STM32开发平台和工具 1.1 STM32芯片介绍 典型微控制器由CPU&#xff08;运算器、控制器&#xff09;、RAM、ROM和输入输出组成。 1.2 STM32核心板 STM32核心板配件&#xff1a; ①JTAG/SWD仿真-下载器 ②通信-下载模块 ③OLED显示屏 1&#xff09; 通信-下载模…

spring的高阶使用技巧1——ApplicationListener注册监听器的使用

Spring中的监听器&#xff0c;高阶开发工作者应该都耳熟能详。在 Spring 框架中&#xff0c;这个接口允许开发者注册监听器来监听应用程序中发布的事件。Spring的事件处理机制提供了一种观察者模式的实现&#xff0c;允许应用程序组件之间进行松耦合的通信。 更详细的介绍和使…

海外市场成 ISV 新掘金地?生成式 AI 如何加速业务创新实践?Zilliz 有话说

期望了解 Zilliz 最新动态&#xff1f;想要与 Zilliz 线下探讨 AI 时代向量数据库的全球化布局思考及典型实践&#xff1f; 机会来啦&#xff01;5 月 10 日&#xff0c;Zilliz 将闪现亚马逊云科技的两场活动现场&#xff08;苏州、西安&#xff09;&#xff0c;与大家共话行业…

Ubuntu将软件图标添加到应用列表

一.简介snap snap和yum&#xff0c;apt一样都是安装包工具&#xff0c;但是snap里的软件源是自动更新到最新版本&#xff0c;最好用 比如Ubuntu的软件商城就是使用的snap软件包 二. Ubuntu软件商城更新 1.ps -ef | grep snap-store 查询并kill snap-store的所有进程 2.sudo …

【仪酷LabVIEW AI工具包案例】使用LabVIEW AI工具包+YOLOv5结合Dobot机械臂实现智能垃圾分类

‍‍&#x1f3e1;博客主页&#xff1a; virobotics(仪酷智能)&#xff1a;LabVIEW深度学习、人工智能博主 &#x1f384;所属专栏&#xff1a;『仪酷LabVIEW AI工具包案例』 &#x1f4d1;上期文章&#xff1a;『【YOLOv9】实战二&#xff1a;手把手教你使用TensorRT实现YOLOv…

C++之STL-priority_queue和仿函数的讲解

目录 一、priority_queue的介绍和使用 1.1 priority_queue的介绍 1.2 priority_queue的基本接口 二、仿函数的介绍 2.1 基本概念 2.2 适用场景 三、模拟实现priority_queue 3.1 向上调整算法 3.2 向下调整算法 3.3 整体框架 一、priority_queue的介绍和使用 1.1 prio…