【Linux网络编程】简单的UDP网络程序

目录

一,socket编程的相关说明

1-1,sockaddr结构体

1-2,Socket API

二,基于Udp协议的简单通信


一,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_pton())将其转换成点分十进制的字符串形式。  

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_INETAF_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_UNIXAF_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地址)。
  • addrlenaddr参数所指向的地址结构的长度。

返回值:

        成功时,返回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,这个参数是必须的。
  • addrlendest_addr 结构体的大小。

返回值:              

        成功时,返回发送的字节数;失败时,返回 -1。

        socket API还有很多,我们暂时先了解这些,后面遇到需要时会进行说明。


二,基于Udp协议的简单通信

        服务器的IP地址一般不指定,因此,下面程序实现时,我们将服务端的IP地址设为0(表示接收任意IP地址),这时只有端口号标识其服务端。

        服务端的端口号我们使用输入的环境变量的方式来确定,形式为:【可执行文件】【十六位的端口号】。其它形式的输入全部出错。这时,客户端只要连接到指定输入服务器的端口号即可完成远程网络连接进行通信。通过服务端,我们可查看客户端的IP和端口号,下面代码演示会看到。

        注意:云服务器的端口号默认都是禁止访问的,若要使用云服务器实现通信,首先需要自己开放云服务器的端口。至于如何开放云服务器的端口号请看此文章:云服务器端口开放

        客户端创建套接字时不用使用bind函数进行绑定(系统会自动绑定)。

        客户端运行的方式这里使用【可执行文件】【连接服务器的IP地址】【十六位的端口号】形式,其它形式的输入全部错误。

        程序总代码请在此链接下观看:UdpSocket代码程序

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

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

相关文章

AI 写作(九)实战项目二:智能新闻报道(9/10)

一、项目概述 在当今信息爆炸的时代&#xff0c;新闻传播行业正面临着前所未有的挑战与机遇。随着科技的飞速发展&#xff0c;人们获取信息的渠道日益多样化&#xff0c;对新闻的时效性、准确性和个性化需求也不断提高。在这样的背景下&#xff0c;AI 写作在智能新闻报道中的重…

针对gitgitee的使用

1.下载git 链接 打开终端&#xff0c;桌面鼠标右键 2.配置密钥 登录gitee。 设置密钥 查看官方文档 跟着教程 复制最后的输出进行密钥添加 验证是否添加成功 3.创建&连接远程仓库 创建仓库 git终端进行配置 远程仓库克隆到本地 桌面终端clone,克隆他人|自己的仓库到本地…

DNS批量解析管理软件有什么用

在复杂的网络环境中&#xff0c;DNS批量解析管理软件犹如一把功能强大的钥匙&#xff0c;开启了高效网络管理的大门&#xff0c;为网络运营和维护带来了诸多便利。 1、对于网络服务提供商而言&#xff0c;DNS批量解析管理软件极大地提高了工作效率 传统的DNS解析管理方式在处…

二叉树遍历的非递归实现和复杂度分析

一&#xff0c;用栈实现二叉树先序遍历 1&#xff0c;原理 我用自己的口水话解释一下&#xff1a;准备一个栈&#xff0c;从根节点开始&#xff0c;先判断栈是否为空&#xff0c;如果否&#xff0c;就弹出一个元素&#xff0c;对弹出元素进行自定义处理&#xff0c;再将它的左…

ElasticSearch-全文检索(一)基本介绍

简介 Elasticsearch&#xff1a;官方分布式搜索和分析引擎 | Elastic 全文搜索属于最常见的需求&#xff0c;开源的Elasticsearch是目前全文搜索引擎的首选。 它可以快速地储存、搜索和分析海量数据。维基百科、StackOverflow、Github都采用它 Elastic的底层是开源库Lucene。但…

65 mysql 的 表元数据锁

前言 这里我们来看一下 mysql 这边的 元数据锁, 术语称之为 MDL 我们这里 忽略它的实现, 我们仅仅看 其具体的使用的地方 因为它的实现 也就可以理解为另外一个 表排他锁, 具体的实现来说 和表排他锁 类似 我们这里 仅仅去了解 在各种类型的语句中 MDL 的使用的地方 lock …

【eNSP】路由基础与路由来源——静态路由实验

路由是数据包从源地址到目的地址的传输路径&#xff0c;静态路由是指网络管理员手动配置的路由条目&#xff0c;用于指定数据包从源地址到目的地址的固定路径。以下是关于静态路由的详细介绍。 一、路由的基础知识点 路由的定义&#xff1a; 路由是指在计算机网络中&#xff…

androidstudio入门到放弃配置

b站视频讲解传送门 android_studio安装包&#xff1a;https://developer.android.google.cn/studio?hlzh-cn 下载安装 开始创建hello-world 1.删除缓存 文件 下载gradle文件压缩&#xff1a;gradle-8.9用自己创建项目时自动生成的版本即可&#xff0c;不用和我一样 https://…

从0开始学习--Day26--聚类算法

无监督学习(Unsupervised learning and introduction) 监督学习问题的样本 无监督学习样本 如图&#xff0c;可以看到两者的区别在于无监督学习的样本是没有标签的&#xff0c;换言之就是无监督学习不会赋予主观上的判断&#xff0c;需要算法自己去探寻区别&#xff0c;第二张…

java算法性能调优:详尽探讨时间复杂度与空间复杂度的分析与优化“

接下来我将带领大家进入Java数据结构的深入学习&#xff0c;让我们一同享受Java数据结构中的奥秘。 一、引言 二、时间复杂度 三、空间复杂度 四、Java中的时间复杂度和空间复杂度 五、优化时间复杂度和空间复杂度 七、时间复杂度和空间复杂度的重要性 一&#xff1a;时间…

「AI Infra 软件开源不是一个选项,而是必然」丨云边端架构和 AI Infra专场回顾@RTE2024

在人工智能和开源技术蓬勃发展的当下&#xff0c;AI Infra 项目正经历着日新月异的变革。从跨平台运行时到云边端 AI 基础设施&#xff0c;再到多模态知识助手&#xff0c;创新浪潮席卷而来。这些进步不仅显著提升了技术指标&#xff0c;也为实时音视频处理、边缘计算、大模型应…

【重生之我要苦学C语言】深入理解指针6

深入理解指针6 sizeof和strlen的对比 sizeof 操作符 整型&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() {int a 10;printf("%zd\n", sizeof(a));printf("%zd\n", sizeof(int));printf("%zd\n", sizeo…

创建vue插件,发布npm

开发步骤&#xff1a;1.创建一个vue项目&#xff0c;2.开发一个组件。 3.注册成插件。 4.vite和package.json配置。5.发布到npm &#xff11;.创建一个vue项目 npm create vuelatest 生成了vue项目之后&#xff0c;得到了以下结构。 在src下创建个plugins目录。用于存放开发的…

Java垃圾回收算法

垃圾回收之标记算法 1、引用计数法 通过判断对象的引用数量来决定对象是否被回收每个对象实例都有一个引用计数器&#xff0c;被引用则1&#xff0c;完成引用则-1 优点&#xff1a; 执行效率高&#xff0c;程序执行受影响小 缺点&#xff1a; 无法检测出循环引用的情况&#…

文献阅读 | Nature Communications:使用自适应图注意自动编码器从空间解析的转录组学中解读空间域

文献介绍 文献题目&#xff1a; 使用自适应图注意自动编码器从空间解析的转录组学中解读空间域 研究团队&#xff1a; 张世华&#xff08;中国科学院数学与系统科学研究院&#xff09; 发表时间&#xff1a; 2022-04-01 发表期刊&#xff1a; Nature Communications 影响因子…

新手小白学习docker第八弹------实现MySQL主从复制搭建

目录 0 引言1 实操1.1 新建主服务器容器1.2 书写配置文件1.3 重启master实例1.4 进入mysql-master容器master容器实例内创建数据同步用户 1.5 新建从服务器容器1.6 书写配置文件1.7 重启slave实例1.8 查看主从同步状态1.9 进入mysql-slave容器1.9.1 配置主从复制1.9.2 查看主从…

学习threejs,使用TWEEN插件实现动画

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.PLYLoader PLY模型加…

HarmonyOS Next星河版笔记--界面开发(5)

1.字符串 1.1.字符串拼接 作用&#xff1a;把两个或多个字符串&#xff0c;拼成一个字符串。&#xff08;通常是用来拼接字符串和变量&#xff09; hello world > helloworld 加好作用&#xff1a;拼接 let name:string 小明 console.log(简介信息,名字是 name) …

24.11.13 机器学习 特征降维(主成份分析) KNN算法 交叉验证(K-Fold) 超参数搜索

导包小总结(不全面): from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.feature_extraction import DictVectorizer(字典数据集的划分) from sklearn.feature_extraction.text import CountVectorizer(特征提取…

基于SpringBoot+RabbitMQ完成应⽤通信

前言&#xff1a; 经过上面俩章学习&#xff0c;我们已经知道Rabbit的使用方式RabbitMQ 七种工作模式介绍_rabbitmq 工作模式-CSDN博客 RabbitMQ的工作队列在Spring Boot中实现&#xff08;详解常⽤的⼯作模式&#xff09;-CSDN博客作为⼀个消息队列,RabbitMQ也可以⽤作应⽤程…