【Linux网络编程】简单的UDP套接字
目录
一,socket编程的相关说明
1-1,sockaddr结构体
1-2,Socket API
二,基于Udp协议的简单通信
三,UDP套接字的应用
3-1,实现英译汉字典
一,socket编程的相关说明
Socket编程是一种网络通信编程技术,它允许两个或多个程序在网络上相互通信,无论这些程序是否运行在同一台计算机上。
在Socket编程中,每个网络通信端点都被称为一个套接字(封装了底层的网络协议,如TCP/IP的细节)。这个套接字支持不同的传输协议,可以看作是两个程序之间打开的一个通信通道,通过这个通道,程序可以在网络上进行数据的传输。
不同主机在网络上进行数据传输时需要拿到拿到对方的端口号(标识主机的应用程序或网络服务,在网络通信中确保将数据包交给哪个主机上的应用程序来处理)和IP地址(互联网上每一台计算机的地址,在网络通信中用于标识主机的位置)。IP地址用于寻找指定机器,找到指定机器后,就需要端口号来找到指定机器下的指定服务或程序。
注意:服务端通常不会给予特定的IP地址。首先,如果指定服务端的IP地址,那么服务端程序只能在特定的网络环境中运行,要是网络环境发生变化(例如,服务器迁移到新的IP地址),则需要重新编译和部署程序。其次,在很多的场景中,服务端程序不仅需要部署在多个服务器上,还需要在不同的机器和网络环境中运行,具有多个网络接口,它的IP地址也可能会动态变化。这时,若多个客户端连接到一个服务端上,指定特定的IP地址会导致连接出错等问题。
1-1,sockaddr结构体
Socket编程中,struct sockaddr
结构体是常用的类型操作,该结构体是用于描述套接字地址的通用结构体,并指定或返回网络地址信息,是一个通用的地址结构体,它通常出现在套接字函数的参数中,在网络编程中广泛使用。运用时,由于网络地址协议格式各有不同,所以该结构体通常会被更具体的地址结构体(如 struct sockaddr_in
或 struct sockaddr_in6
)所替代,这些结构体提供了更详细的地址信息,需要时,一般都是通过指针将sockaddr
进行强制转换,具体使用请看后面代码。
struct sockaddr_in
是基于IPv4编程的网络环境中使用的数据结构。这个结构里主要有三部分信息:地址类型、端口号、IP地址。
struct sockaddr_in
{
地址族,对于 IPv4 来说是 AF_INET
注意:地址族是将不同的网络层协议(如IPv4、IPv6等)进行分类的一种方式。它允许网 络设备根据地址族来识别和处理不同协议的数据包,指定源字符串的地址类型。一般用 于区分IPv4和IPv6。
sa_family_t sin_family;端口号,由于端口号也需要经过网络传送(网络通信时需要拿到对方的端口号进行通 信),所以传递网络前需要使用 htons()函数将其转换为网络字节序
uint16_t sin_port;包含一个 32 位IPv4 地址的结构体
struct in_addr sin_addr;
用来将结构大小填充到与 struct sockaddr 相同的大小,通常被设置为零。
char sin_zero[8];
};typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr; 一个 32 位的IPv4 地址
};
注意:
1,网络数据传输时,IP地址也需要经过网络传输,所以这里需要把点分十进制的IP地址(字符串类型)转换成网络字节序
2,
inet_addr()
用来表示一个IPv4的IP地址(32位的整数)。通常使用inet_pton()
或inet_addr()
函数来将点分十进制的 IPv4 地址字符串转换为4字节的网络字节序(大端序)3,
inet_pton()
和inet_addr()
虽然都是用于将IP地址(字符串形式)转换为网络字节序的二进制形式,但是,inet_pton()
不仅支持IPv4,还支持 IPv6 地址的转换,除此外,inet_pton()
通常还是线程安全的(inet_addr()
可能不是线程安全的)。inet_pton()
是较新的函数,提供了更广泛的功能和更好的错误处理,但是该函数运用起来比较复杂。4,当网络IP地址传送到主机上时,需要用特定的函数(比如:inet_ntoa())将其转换成点分十进制的字符串形式。
inet_addr:
格式:in_addr_t inet_addr(const char *cp);
参数:
cp
:指向一个以空字符结尾的字符串,该字符串表示一个点分十进制格式的IPv4 地址(例如,"192.168.1.1")。返回值:成功时,返回该IP地址的网络字节序表示(一个
in_addr_t
类型的值)。如果 输入字符串不是有效的IPv4地址,函数返回INADDR_NONE
(通常是-1
,在<netinet/in.h>
头文件中定义)。inet_pton:
格式:int inet_pton(int af, const char *src, void *dst);
参数:
af
:地址族。一般是AF_INET
或AF_INET6
src
:指向一个以空字符结尾的字符串,该字符串表示一个点分十进制格式的IPv4 地址(AF_INET
)或十六进制格式的IPv6地址(AF_INET6
)
dst
:指向一个缓冲区,该缓冲区存储转换后的网络字节序地址返回值:
成功时,返回
1。
如果输入字符串不是有效的地址格式,返回
0。
如果发生系统级错误(例如,参数不合法),返回
-1。
inet_ntoa:
功能:将网络字节序的二进制IP地址转换为点分十进制的IP地址字符串
格式:char *inet_ntoa(struct in_addr in);
参数:in:表示一个32位的IPv4地址的结构体,即需要转换网络字节序的二进制IP地址
返回值:成功时,返回一个表示点分十进制的IP地址的字符串;失败时,返回NULL。
1-2,Socket API
socket API是一层抽象的网络编程接口,其中,API代表应用程序编程接口。在socket编程中,API提供了一系列用于网络通信的函数和接口。这些API函数封装了底层网络通信的复杂性,为开发者提供了简单而强大的接口。通过API,应用程序可以调用操作系统或其他软件服务提供的函数和程序,以实现特定的功能或操作。常见的socket API包括:
1,socket。用于创建一个新的套接字,相关说明如下:
头文件:
#include <sys/types.h>
#include <sys/socket.h>格式:
int socket(int domain, int type, int protocol);
参数说明:
- domain:指定通信时使用的协议族。常用的协议族有:
AF_INET
:IPv4的协议族。IPv4地址类型定义在常数AF_INET中AF_INET6
:IPv6的协议族。IPv6地址类型定义在常数AF_INET6中AF_UNIX
或AF_LOCAL
:本地通信协议族(通常用于同一台机器上的进程间通信)。- type:指定套接字类型。常用的套接字类型有:
SOCK_STREAM
:流式套接字,用于TCP连接。SOCK_DGRAM
:数据报套接字,用于UDP连接。SOCK_RAW
:原始套接字,允许对IP层及以下的数据进行直接访问和操作。- protocol:通常设置为0,表示自动选择该domain和type组合下的默认协议。特殊情况下会设置特定的协议,这里先不考虑。
返回值:
成功时,该函数返回一个非负数的套接字描述符(也可以理解为文件描述符,因为Linux一切皆文件),该描述符在后续的网络操作中用于标识该套接字;失败时,返回-1。
2,bind。函数用于将一个套接字与一个特定的地址(通常是IP地址和端口号,即sockaddr结构体)关联起来。在服务器程序中,这通常是第一步,因为服务器需要在一个特定的端口上监听来自客户端的连接请求,即绑定端口号。
注意:在计算机网络编程中,bind
函数主要用于服务器端,而不是客户端。服务端是确定的,需要绑定到一个特定的 IP 地址和端口号,需要在应用程序启动时绑定,以便客户端能够连接到它。客户端一般可以打开多个服务(比如:打开淘宝、百度、抖音等),若是使用bind
函数连接固定的端口号,可能会导致不同的网络服务使用到同一个端口号,导致服务冲突,因此客户端通常是在首次发送数据的时候由操作系统动态分配一个临时的端口号来进行通信,不需要使用专门函数绑定到特定的 IP 地址和端口号。
头文件:
#include <sys/types.h>
#include <sys/socket.h>格式:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
sockfd
:要绑定套接字的文件描述符。addr
:指向一个sockaddr
结构的指针,该结构包含了要绑定的地址和端口信息。在实际使用中,通常会使用sockaddr_in
结构(基于IPv4地址)或sockaddr_in6
结构(基于IPv6地址)。addrlen
:addr
参数所指向的地址结构的长度。返回值:
成功时,返回0;失败时,返回-1。
3,listen。该函数用于将套接字设置为监听状态,以接受来自客户端的连接请求。这个函数通常在服务器程序中调用,在调用 bind
函数时将套接字与特定地址(IP地址和端口号)关联之后使用。
头文件:
#include <sys/types.h>
#include <sys/socket.h>格式:
int listen(int sockfd, int backlog);
参数说明:
sockfd
:要监听套接字的文件描述符。backlog
:指定系统内核应为相应套接字排队的最大连接数。一般设置为SOMAXCONN
,即使用系统定义的最大值。返回值:
成功时,返回0;失败时,返回-1。
4,recvfrom。该函数用于从套接字中接收数据,默认情况下,若 recvfrom
在没有数据可读的情况下被调用它将会阻塞等待。该函数特别是在处理无连接协议(如 UDP)时经常使用。
这里先说明下 socklen_t 类型,它是一个无符号整数类型,其长度至少为32位(具体大小可能因操作系统和平台而异),用于指定套接字地址结构的大小。
头文件:
#include <sys/types.h>
#include <sys/socket.h>格式:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
注意:
ssize_t是一个平台相关的类型,在32位机器上,ssize_t通常等同于int类型;在64位机器上,它通常等同于long int类型。
参数说明:
sockfd:套接字文件描述符,表示接收数据的套接字。
buf:指向接收数据缓冲区的指针。
len:指定缓冲区
buf
的大小,即最多可以接收的数据字节数。flags:通常设置为 0(可以是某些特性功能的字段,这里不做说明)。
src_addr:指向
sockaddr
结构的指针,用于存储发送方地址信息。如果不需要此信息,可以设置为NULL
。addrlen:指向一个在调用时包含
src_addr
结构大小的指针,在返回时包含实际写入src_addr
的大小。如果src_addr
是NULL
,则addrlen
也应该是NULL
。返回值:
成功时,返回接收到的字节数(如果连接已正常关闭,则返回 0);失败时,返回 -1。
5,sendto。该函数主要用于发送数据到指定的套接字,是网络编程中发送数据的函数之一。
头文件:
#include <sys/types.h>
#include <sys/socket.h>格式:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
注意:
ssize_t是一个平台相关的类型,在32位机器上,ssize_t通常等同于int类型;在64位机器上,它通常等同于long int类型。
参数说明:
sockfd
:套接字文件描述符,表示要发送数据的套接字。buf
:指向包含要发送数据的缓冲区的指针。len
:要发送的数据的长度(以字节为单位)。flags
:通常设置为 0(可以是某些特性功能的字段,这里不做说明)。dest_addr
:指向sockaddr
结构体的指针,表示数据发送的目标地址信息。对于 TCP 连接,这个参数通常不需要,因为连接已经建立了目标地址;但对于 UDP,这个参数是必须的。addrlen
:dest_addr
结构体的大小。返回值:
成功时,返回发送的字节数;失败时,返回 -1。
socket API还有很多,我们暂时先了解这些,后面遇到需要时会进行说明。
二,基于Udp协议的简单通信
服务器的IP地址一般不指定,因此,下面程序实现时,我们将服务端的IP地址设为0(表示接收任意IP地址),这时只有端口号标识其服务端。
服务端的端口号我们使用输入的环境变量的方式来确定,形式为:【可执行文件】【十六位的端口号】。其它形式的输入全部出错。这时,客户端只要连接到指定输入服务器的端口号即可完成远程网络连接进行通信。通过服务端,我们可查看客户端的IP和端口号,下面代码演示会看到。
注意:云服务器的端口号默认都是禁止访问的,若要使用云服务器实现通信,首先需要自己开放云服务器的端口。至于如何开放云服务器的端口号请看此文章:云服务器端口开放
客户端创建套接字时不用使用bind函数进行绑定(系统会自动绑定)。
客户端运行的方式这里使用【可执行文件】【连接服务器的IP地址】【十六位的端口号】形式,其它形式的输入全部错误。
程序总代码请在此链接下观看:UdpSocket代码程序
三,UDP套接字的应用
3-1,实现英译汉字典
这里设置了Dict.txt字典文件,里面对应的是可以查找到的单词及对应的汉语,然后,在Dict.hpp 中,简单的实现了字典类的封装。这里需提一点,由于字典类需要将Dict.txt 文件中的数据加载到类中,所以这里我们使用C++文件流ifstream。
在C++中,ifstream
是一个类,用于从文件读取数据。它是C++标准库中的一部分,特别是属于输入输出(I/O)流库的一部分(输入文件流)。ifstream
继承自istream
类,因此它提供了所有从输入流中读取数据的功能,但专门用于文件输入。通过使用ifstream
,我们可以打开文件、读取文件内容、检查文件状态(如是否到达文件末尾),以及关闭文件等操作。相关的常用操作请在此链接下观看:ifstream文件流的使用
服务端 UdpServer.hpp 中,基于应用服务的实现一般是在 recvfrom 和 sendto函数之间实现。客户端发送的需要查找的单词传送给服务端后,服务端进行查找,将查找到的信息发送给客户端,这里我们使用 function 和 bind 包装器来实现这一功能。详细代码及说明请看此链接:英译汉字典的实现
相关文章:

【Linux网络编程】简单的UDP套接字
目录 一,socket编程的相关说明 1-1,sockaddr结构体 1-2,Socket API 二,基于Udp协议的简单通信 三,UDP套接字的应用 3-1,实现英译汉字典 一,socket编程的相关说明 Socket编程是一种网络通信…...

在Vue中使用Excalidraw实现在线画板
概述 Excalidraw是一个非常好用的画图板工具,但是是用React写的,本文分享一种在Vue项目中使用的方法。 效果 实现 Excalidraw简介 这篇文章(Excalidraw 完美的绘图工具:https://zhuanlan.zhihu.com/p/684940131)介绍的很全面,…...

游戏+AI的发展历程,AI技术在游戏行业的应用有哪些?
人工智能(AI)与游戏的结合,不仅是技术进步的体现,更是人类智慧的延伸。从最初的简单规则到如今的复杂决策系统,AI在游戏领域的发展历史可谓波澜壮阔。 早在2001年,就有研究指出游戏人工智能领域࿰…...

Methode Electronics EDI 需求分析
Methode Electronics 是一家总部位于美国的全球性技术公司,专注于设计和制造用于多个行业的电子和电气组件,产品涵盖汽车、工业、电信、医疗设备以及消费电子等多个领域,提供创新的解决方案。 填写Methode_EDI_Parameters_Template Methode_…...

2023AE软件、Adobe After Effects安装步骤分享教程
2023AE软件是一款由Adobe公司开发的视频编辑软件,也被称为Adobe After Effects。它在广告、电影、电视和网络视频等领域广泛应用,用于制作动态图形、特效、合成和其他视觉效果。该软件支持多种视频和音频文件格式,具有丰富的插件和预设&#…...

【前端】JavaScript 变量引用、内存与数组赋值:深入解析三种情景
博客主页: [小ᶻZ࿆] 本文专栏: 前端 文章目录 💯前言💯场景一:直接赋值与重新引用为什么结果不是 [3, 4, 5]?1. 引用与赋值的基本概念2. 图示分析 关键总结 💯场景二:引用指向的变化为什么…...
本地项目运行提示跨域问题
项目背景:我使用phpwebstudy在本地搭建了一个项目,然后前端是http://localhost:8080/ 后端我直接创建了一个本地域名,例如www.abc.com 然后vue.config.js配置如下,这个配置在我所有线上环境是没有任何问题的 devServer: {proxy…...

C++ —— string类(上)
目录 string的介绍 string类功能的使用介绍 constructor —— 构造 介绍使用(1)(2)(4) :构造、拷贝构造、带参构造 介绍(3):拷贝string类对象的一部分字符…...

React Native Mac 环境搭建
下载 Mac 版Android Studio 下载 安装 JDK 环境 Flutter 项目实战-环境变量配置一 安装 Node.js 方式一 通过Node.js 官网下载 下载完成后点击安装包进行安装 安装完成...
Python Web 开发的路径管理艺术:FastAPI 项目中的最佳实践与问题解析20241119
Python Web 开发的路径管理艺术:FastAPI 项目中的最佳实践与问题解析 引言:从路径错误到模块化管理的技术旅程 在现代 Python Web 开发中,路径管理是一个常常被忽视却非常重要的问题。尤其是在使用像 FastAPI 和 Tortoise ORM 这样的框架时…...

Rust derive macro(Rust #[derive])Rust派生宏
参考文章:附录 D:派生特征 trait 文章目录 Rust 中的派生宏 #[derive]基础使用示例:派生 Debug 派生其他常用特征示例:派生 Clone 和 Copy 派生宏的限制和自定义派生自定义派生宏上面代码运行时报错了,以下是解释 结论…...

springboot嗨玩旅游网站
摘 要 嗨玩旅游网站是一个专为旅行爱好者打造的在线平台。我们提供丰富多样的旅游目的地信息,包括景点信息、旅游线路、商品信息、社区信息、活动推广等,帮助用户轻松规划行程。嗨玩旅游网站致力于为用户提供便捷、实用的旅行服务,让每一次旅…...

杰发科技AC7840——EEP中RAM的配置
sample和手册中示例代码的sram区地址定义不一样 这个在RAM中使用没有限制,根据这个表格留下足够空间即可 比如需要4096字节的eep空间,可以把RAM的地址改成E000,即E000-EFFF,共4096bytes即可。...

从零开始的c++之旅——map_set的使用
1.序列式容器和关联式容器 序列式容器:逻辑结构为线性序列的数据结构,两个位置之间没有紧密的关系,比如两者交换一下还是序列式的容器,例如string,vector,deque,array等。 关联式容器࿱…...
Docker中的一些常用命令
find / -type f -name “文件名” 2>/dev/null 寻找所有目录中的这个文件 pwd 查看当前目录的地址 docker pull 镜像名 强制拉镜像 docker run 运行docker systemctl daemon-reload 关闭docker systemctl start docker 启动docker systemctl restart docker 重启docker /…...

自存 sql常见语句和实际应用
关于连表 查询两个表 SELECT * FROM study_article JOIN study_article_review 查询的就是两个表相乘,结果为两个表的笛卡尔积 相这样 这种并不是我们想要的结果 通常会添加一些查询条件 SELECT * FROM study_articleJOIN study_article_review ON study_art…...
python | argparse模块在命令行的使用中的重要作用
import argparseclass TestCases:def __init__(self, nameNone, expect_resultNone):self.name nameself.expect expect_resultself.parser argparse.ArgumentParser() # 创建命令解析器self.add_arguments() # 方法 : 添加命令self.args, _ self.parser.par…...

【HCIP]——OSPF综合实验
题目 实验需求 根据上图可得,实验需求为: 1.R5作为ISP:其上只能配置IP地址;R4作为企业边界路由器,出口公网地址需要通过PPP协议获取,并进行CHAP认证。(PS:因PPP协议尚未学习&#…...

PW系列工控电脑复制机:效率与精度双重提升
工控电脑复制应用:效率与精度的双重提升 随着现代企业对大数据、数据备份、和跨平台兼容性需求的快速增长,工控电脑已成为数据密集型产业的核心设备。针对工控环境中大量数据复制的特殊需求,PW系列NVMe/SATA PCIe SSD复制机(如PW…...

学习QT第二天
QT6示例运行 运行一个Widgets程序运行一个QT Quick示例 工作太忙了,难得抽空学点东西。-_-||| 博客中有错误的地方,请各位道友及时指正,感谢! 运行一个Widgets程序 在QT Creator的欢迎界面中,点击左侧的示例…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...