网络编程——Udp套接字

news2024/9/22 13:30:20

在这里插入图片描述

文章目录

  • 1. 简单的UDP网络程序
    • 1.1 日志的打印
    • 1.2 服务端初始化
    • 1.3 启动服务器并提供服务
    • 1.4 客户端
    • 1.5 客户端发送的消息
    • 1.6 服务端的构造函数和析构函数
    • 1.7 本地测试
    • 1.8 服务端回复消息给所有客户端

1. 简单的UDP网络程序

在这里插入图片描述
我们把udp的协议封装成一个类。

下面我们就开始认识第一个接口:
在这里插入图片描述
这个函数的作用是创建套接字。
第一个参数:叫做socket的域,代表你是本地通信还是网络通信。本地通信就填AF_UNIX,网络通信就填AF_INET

第二个参数:叫做套接字的类型,决定了我们通信时候对应的报文类型。常用的有流式(SOCK_STREAM)和用户数据报(SOCK_DGRAM)

第三个参数:协议类型,在网络通信中设置成0就行了

返回值
在这里插入图片描述
此函数执行成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况。既然是文件描述符,OS就会创建struct file结构,用来指向网络通信的属性和方法,然后我们用文件描述符来标识你打开的文件的信息。
在这里插入图片描述
这样sockfd就创建成功。

1.1 日志的打印

然后我们再写一个打印日志的头文件:
在这里插入图片描述
第一个参数传的是日志等级,第二个参数传的是格式化输出是什么。
必须在[0,3]这个范围才能进来。

可变参数我们使用时,需要定义的东西:
在这里插入图片描述
va_start是将离可变参数最近的参数初始化。
在这里插入图片描述
va_list其实就是一个char*的指针,va_end是将这个指针设置成NULL。

va_arg的意思是:提参。如果我们是这样传的:
logMessage(DEBUG, “%d”, 10)
在这里插入图片描述
那么这里的x就会被提取成10。
在这里插入图片描述
我们再看一下关于这些函数。vsnprintf()用于向一个字符串缓冲区打印格式化字符串,且可以限定打印的格式化字符串的最大长度。

第一个参数:用于缓存格式化字符串结果的字符数组

第二个参数:限定最多打印到缓冲区sbuf的字符的个数为n-1个,因为vsnprintf还要在结果的末尾追加\0。

第三个参数:格式化限定字符串

第四个参数:可变长度参数列表

返回值:成功打印到第一个参数中的字符的个数,不包括末尾追加的\0。如果格式化解析失败,则返回负数
在这里插入图片描述
这样就可以把格式化字符串打印到logInfo数组里。
在这里插入图片描述
如果日志等级是FATAL(致命的),那么就设置成stderr,如果不是就设置成stdout。

下面我们就可以进行打印了:
在这里插入图片描述
第一个参数是日志等级,第二个参数是时间,第三个参数是哪个用户打印的,第四个参数是消息内容,在这里就是logInfo。
在这里插入图片描述
这里可以用环境变量来查看当前用户。
在这里插入图片描述
这样我们就可以进行规范的日志打印。
在这里插入图片描述

1.2 服务端初始化

在这里插入图片描述
创建好套接字后,我们需要绑定网络了。怎么绑定?我们看一下接口:
在这里插入图片描述
服务端将把用于通信的地址和端口绑定到socket上。
第一个参数:需要绑定的socket
第二个参数:是指向一个结构为sockaddr参数的指针,sockaddr中包含了地址、端口和IP地址的信息

因为我们是要网络通信,所以我们要设置sockaddr_in这个结构体。

第三个参数:是第二个参数的大小
在这里插入图片描述
我们创建这个结构体对象时,需要包含头文件:
在这里插入图片描述
在这里插入图片描述
下面我们使用这个local的时候,我们需要给它初始化:
在这里插入图片描述
或者使用memset来初始化。
在这里插入图片描述
下面我们需要将local里面的内容设置一下:
在这里插入图片描述
sin_family就是你要填的是网络通信还是本地通信。sin_port就是要设置的端口号,因为服务端口号要发送到网络中,所以要进行转换。

有了端口号还需要IP地址:
在这里插入图片描述
我们知道:IP地址是字符串风格点分十进制,它是4字节地址,那么我们可以把它转成uint32_t,因为它也是4字节。
在这里插入图片描述
我们可以看到sin_addr它的类型是in_addr。
在这里插入图片描述
in_addr里面有一个in_addr_t,它的类型是uint32_t。
在这里插入图片描述
这里的意思是把s_addr设置成:如果传的IP地址是空,我们就设置成这个宏,因为IP地址需要发到网络,所以需要转化成网络字节序。否则就设置成这个字符串转成的uint32_t。

这个inet_addr函数的意思是:
在这里插入图片描述
把这个字符串点分十进制转成in_addr_t类型。

这个宏就是0:
在这里插入图片描述
它的意思是:会绑定所有的IP
inet_addr的意思是:指定填充确定的IP,特殊用途,或者测试时使用,除了做转化,还会自动给我们转成网络字节序

其实这个宏为0,转不转网络字节序其实意义不大。

云服务器有一些特殊情况:禁止你bind云服务器上的任何确定IP, 只能使用INADDR_ANY,如果是虚拟机,随意

那么这个local是在哪里开辟的空间
答案是:在用户栈上,它是一个临时变量,需要写入内核中
在这里插入图片描述

1.3 启动服务器并提供服务

我们要进行网络读写,就需要这个函数:
在这里插入图片描述
recvfrom函数是用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。

第一个参数就是:我们要接受消息的套接字
第二个参数就是:接受消息要存放的缓冲区
第三个参数就是:缓冲区长度
第四个参数就是:调用操作方式,一般设置为0,意思就是阻塞等待
第五个参数就是:输出型参数,用来指定欲接收数据的网络地址
第六个参数就是:输入输出型参数,指向第五个参数长度值

比如,客户端要给我们发送消息,就会保存在第五个参数中。

返回值:成功则返回接收到的字符数,失败返回-1
在这里插入图片描述
这里就开始读取客户端的消息。
在这里插入图片描述
读取成功就设置成字符串,读取失败就打印错误日志,然后重新读取。
在这里插入图片描述
不仅需要读取对方的消息内容,也要读取对方的IP和端口号,因为服务端也可能给对方发消息。

这里有一个函数inet_ntoa:
在这里插入图片描述
这个函数是将4字节的IP转换成字符串风格的IP。
在这里插入图片描述
最后进行打印日志。

1.4 客户端

如果一个客户端要连接server必须知道server对应的ip和port

既然如此,那么我们客户端的运行格式是:./udpClient server_ip server_port。
在这里插入图片描述
如果输入的个数不对,就打印使用手册,然后获取我们要访问的服务器的IP和端口号。

在前面的知识,我们学过,两个主机在网络上通信,其实是两个进程在通信,那么客户端也需要创建套接字信息。
在这里插入图片描述
那么客户端需不需要bind呢
肯定是需要的。但是不需要用户自己bind,而是os自动给你bind

我们知道:所有的客户端软件与服务器通信的时候,客户端必须要有自己的IP和端口号,服务器也必须要有自己的IP和端口号。

那么为什么客户端不需要我们自己绑定呢
client很多,不能给客户端bind指定的port,port可能被别的client使用了,你的client就无法启动了。OS会自己生成端口号帮你去bind,当你不用的时候,会自动帮你销毁

那么为什么服务端需要我们自己绑定呢
server提供的服务,必须被所有人知道,并且它不能随意改变
在这里插入图片描述
然后我们填充一下服务器的内容,下一步就可以发送了。

1.5 客户端发送的消息

在这里插入图片描述
怎么发送给服务器呢?我们来看一下这个函数:
在这里插入图片描述
这个sendto函数第一个参数就是你的套接字,第二个参数就是你要发送的缓冲区里面的消息,第三个参数是你要发送消息的长度,第四个是调用操作方式,一般设置为0,意思就是阻塞等待。第五个参数就是你要给谁发送。
在这里插入图片描述
然后我们可以关闭套接字文件描述符。
在这里插入图片描述

1.6 服务端的构造函数和析构函数

在这里插入图片描述
我们要创建一个UdpServer,我们要传端口号和IP地址。
在这里插入图片描述
在这里插入图片描述
我们在输入命令时的格式是:./udpServer port [ip],这个端口号是必须带的,但是IP地址可带可不带。不过在云服务器上,IP地址是不能被指定的。
如果输入的参数个数不一样,就打印一下使用手册。
因为得到的是char*的字符串,所以我们需要将它转成整数。
然后创建服务后,初始化,启动就行。

1.7 本地测试

在这里插入图片描述
我们在这里先启动服务器,可以看到它的套接字和bind都成功了。现在阻塞等待。
端口号: 从0到1023是公认端口,我们尽量不要使用这些端口
在这里插入图片描述
netstat -nupl这个命令是查看网络UDP类型的端口。可以看到服务已经启动了。

下面我们继续启动客户端:
在这里插入图片描述
这个127.0.0.1这个IP地址叫做本地环回,在本主机上通信。它通过网络协议栈时不会发送到网络,而是发送到主机的另外一个进程的缓冲区。

下面我们就可以发消息了:
在这里插入图片描述
那么如果客户端给服务器发送消息后,服务器怎么给我们回复呢
在这里插入图片描述
我们把客户端发送的消息中的小写字母转化成大写字母,存到outbuffer缓冲区里,然后sendto给客户端。
在这里插入图片描述
我们把消息存到buffer缓冲区里,然后打印出来。

运行结果:
在这里插入图片描述

1.8 服务端回复消息给所有客户端

那么客户端有很多,我们该如果把所有的客户端发送的消息都显示出来给每一个客户端呢?
在这里插入图片描述
我们这里用一个哈希表来存放在线客户端。前面存放的是一些信息,后面方的是这个客户端的sockaddr_in。
在这里插入图片描述
在这里插入图片描述
不存在就把这个客户端的信息添加进去。
在这里插入图片描述
在这里插入图片描述
我们把缓冲区的消息加上这个客户端的IP和端口号,发送到每一个客户端里。

那么客户端又需要做什么呢?
在这里插入图片描述
我们把服务器对象给定义到全局。
在这里插入图片描述
创建一个线程,主线程发送消息给服务器。
在这里插入图片描述
新线程去执行接收消息,并打印。
在这里插入图片描述
我们先创建一个命名管道。
在这里插入图片描述
每个客户端都可以在这里看到。

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

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

相关文章

SpringBoot使用Swagger配置API接口文档

💧 概述 Swagger是一个用于设计、构建和文档化 RESTful API 的开源框架。它提供了一组工具,使得开发人员能够更轻松地定义、描述和测试API接口。 具体来说,Swagger包含以下几个核心组件: Swagger规范(Swagger Specif…

【CTF-Reverse】IDA动态调试,反调试技术

在本专栏前两篇文章中,带领大家讲解了逆向加密算法,AES,TEA,RC4,Base64加密算法,并带领大家识别各种密码算法特征,这一篇文章来带领大家学习在逆向过程中的动态调试:IDA动态调试,反调试技术。 …

5SHY3545L0016 3BHB020720R0002可控硅模块IGCT

​ 5SHY3545L0016 3BHB020720R0002可控硅模块IGCT 5SHY3545L0016 3BHB020720R0002可控硅模块IGCT 1) dcs系统往往具有丰富的自诊断功能。根据报警,可以直接找到故障点,并且还可通过报警的消除来验证维修结果。 2) 通信接头接触不良会引起通信故障,确认通信接头接触不良后,可以…

ssm企业网站的设计与实现-计算机毕设 附源码82639

ssm企业网站的设计与实现 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中…

docker安装sentinel

关于如何安装docker 可以看我的这篇文章 ​​​​​​http://t.csdn.cn/3jKPm 第一步:拉取镜像 docker pull bladex/sentinel-dashboard 这里不加版本号默认拉取最新版本 第二步:查看已经安装的镜像 docker images 看到这个就是安装好了 第三步&…

基于Java+Swing实现飞机大战游戏

基于JavaSwing实现飞机大战游戏 一、系统介绍二、功能展示三、其他系统四、获取源码 一、系统介绍 基于Java的飞机大战游戏主要需要我方飞机和敌方飞机,还有子弹,特殊nPC,开始背景,结束背景,以及背景音乐。我方飞机可…

chatGPT对企业的发展有什么影响

ChatGPT目前正在全世界范围内掀起风暴,成为炙手可热的一个名词。作为基于人工智能的工具的最新产品,目前ChatGPT呈现给我们的似乎只是足够有趣,且从目前已知的信息来看,它似乎还没有任何商业运作相关的计划,大多应用聚…

webrtc stun协议

STUN(Simple Traversal of User Datagram Protocol Through Network Address Translators),即简单的用UDP穿透NAT,是个轻量级的协议,是基于UDP的完整的穿透NAT的解决方案。它允许应用程序发现它们与公共互联网之间存在…

死磕AI大模型网络,鹅厂出招了!

2023年,以ChatGPT为代表的AIGC大模型全面崛起,成为了整个社会关注的焦点。 大模型表现出了强悍的自然语言理解能力,刷新了人们对AI的认知,也掀起了新一轮的“算力军备竞赛”。 大家都知道,AIGC大模型的入局门槛是很高的…

西门子S7-1200系列PLC输入/输出接线

西门子S7-1200是一款紧凑型、模块化的PLC,可完成简单逻辑控制、高级逻辑控制、HMI 和网络通信等任务。下面分享S7-1200系列PLC输入/输出接线图给大家。 CPU 1211C 接线图 CPU 1211C AC/DC/继电器 (6ES7 211-1BE40-0XB0) ① 24 VDC 传感器电源 ② 对于漏型输入将负…

KingbaseES的学习心得和知识总结(三)|Kingbase数据库性能调优工具sys_kwr插件的简介和使用

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、KingbaseES V8产品文档首页,点击前往 2、Kingbase 文档库,点击前往 3、北京人大金仓信息技术股份有限公司 官网首页,点击前往…

单片机——时间表程序加仿真

一、程序 #include <REG52.h> #include "main.h" sbit key1P3^0; sbit key2P3^1; sbit key3P3^2; sbit key4P3^3; sbit SWP1^0; unsigned char code SEG[]{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8E,0x86}; unsigned char i,cp,cp1,flash,key…

Python小白必看

Python学习计划&#xff1a; 1.先学习Python基础知识&#xff0c;包括&#xff1a; 变量、数据类型、运算符条件语句、循环语句函数、模块、包 2.掌握Python的常用库和框架&#xff0c;例如&#xff1a; NumPy&#xff1a;用于科学计算、数据分析等Pandas&#xff1a;用于数…

Vue表单验证,表单填写完成无法通过rules验证问题

表单校验使用的是ElementUI官网的表单校验规则&#xff0c;但是表单在填写完成后还是通不过校验&#xff0c;这就需要进行相应的检查 1.检查rules与ref&#xff0c;rules与ref的名字可以随便定义&#xff0c;但是要确保在这块写的与在data中定义的一致 2.检查<el-form-ite…

Pandas 解决保存H5文件发生异常问题

代码&#xff1a; #保存h5文件 #指定文件路径和读写模式 hdpd.HDFStore(mystock.h5,w) #将my的数据存入到hd中 hd[data]my #关闭文件 hd.close() 发生异常&#xff1a; 原因&#xff1a;缺少pytables 解决&#xff1a; 执行命令 pip install tables 安装好之后重启jupyter内核…

2023年1月至4月天猫平台美妆品类销售数据分析

如今&#xff0c;随着人们消费观念的突破&#xff0c;越来越多的人用美妆来诠释个性表达&#xff0c;美丽经济获得更多关注&#xff0c;化妆品消费理念逐渐增强&#xff0c;因此&#xff0c;美妆市场也形成了较大的规模。 根据鲸参谋电商数据显示&#xff0c;2023年1月至4月&am…

争取一文说透NuGet

一、NuGet是什么? NuGet是一个为大家所熟知的Visual Studio扩展&#xff0c;通过这个扩展&#xff0c;开发人员可以非常方便地在Visual Studio中安装或更新项目中所需要的第三方组件&#xff0c;同时也可以通过NuGet来安装一些Visual Studio的插件等。 二、官网&#xff1a;…

驱动开发:内核读写内存多级偏移

让我们继续在《内核读写内存浮点数》的基础之上做一个简单的延申&#xff0c;如何实现多级偏移读写&#xff0c;其实很简单&#xff0c;读写函数无需改变&#xff0c;只是在读写之前提前做好计算工作&#xff0c;以此来得到一个内存偏移值&#xff0c;并通过调用内存写入原函数…

Qt绘图高级编程-绘制文本

注意&#xff1a;以下代码是在paintEvent函数中使用的&#xff0c;坐标是在文本的左下角。 1、设置字体样式 /*-----------1、设置字体样式-----------*///设置画家写字的字体//字体名&#xff0c; 字体大小&#xff0c;粗体&#xff0c;是否斜体QFont font( "楷体"…

芝奇幻锋戟Z5 RGB DDR5-7200 24GB内存评测:稳上7800MHz、温度只有56度

一、前言&#xff1a;7200MHz CL36高频内存仅需1.35V电压 在DDR4年代&#xff0c;三星B-Die是当之无愧的超频王者&#xff0c;而今DDR5已然成为主流&#xff0c;大家公认的最好超频的颗粒是SK海力士A-Die。 但并不是每一款采用了海力士A-Die颗粒的内存条都会有强悍的超频能力&a…