Linux--Socket编程UDP

前文:Socket套接字编程

UDP协议特点

  • 无连接:UDP在发送数据之前不需要建立连接,减少了开销和发送数据之前的时延。
  • 尽最大努力交付:UDP不保证可靠交付,主机不需要维持复杂的连接状态表。
  • 面向报文:UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。
  • 首部开销小:UDP的首部只有8个字节,比TCP的20个字节要短。
  • 支持多种交互通信:UDP支持一对一、一对多、多对一和多对多的交互通信。

大体思路

将通过客户端与服务端的创建,实现客户端能够与服务端进行通信;

利用Socket编程接口,实现双端互通;

UdpServer.hpp

包含一个udp服务端的类,通过一些成员函数,能够实现对应创建类对象,进行初始化和启动对应服务端;
在这里插入图片描述
对于服务器来说,只需要创建对应的端口号,IP地址这里为本地地址(已经确定)。

代码

#pragma once#include<iostream>
using namespace std;
#include"Log.hpp"
#include<string>
#include<cerrno>
#include<cstring>
#include<cstdlib>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include"InetAddr.hpp"
//描述错误码
enum
{SOCKET_ERROR =1,BIND_ERROR,USAGE_ERROR
};
const static int defaultfd = -1;//默认文件描述符为无
class UdpServer
{
public:UdpServer(uint16_t port):_sockfd(defaultfd),_port(port),_isrunning(false){}void InitServer(){//1.创建udp socket 套接字 _sockfd = socket(AF_INET,SOCK_DGRAM,0);if(_sockfd<0){LOG(FATAL,"socket error, %s, %d\n",strerror(errno),errno);exit(SOCKET_ERROR);}LOG(INFO,"socket create success,sockfd: %d\n",_sockfd);//2 先填充sockadd_in结构struct sockaddr_in local;bzero(&local,sizeof(local));local.sin_family=AF_INET;local.sin_port= htons(_port);//htons:将主机字节序转换为网络字节序//local.sin_addr.s_addr = inet_addr(_ip.c_str());local.sin_addr.s_addr=INADDR_ANY;//INADDR_ANY告诉套接字监听来自任何IP地址的连接。这对于服务器来说非常有用,因为服务器通常需要能够接受来自客户端网络上任何位置的连接请求。//再通过函数bind将套接字和网络信息连接起来int n= bind(_sockfd,(struct sockaddr* )&local,sizeof(local));if(n<0){LOG(FATAL,"bind error,%s, %d\n",strerror(errno),errno);exit(BIND_ERROR);}LOG(INFO,"socket bind success\n");}//通过循环不断接收客户端的数据,打印出对应的内容void Start(){_isrunning = true;while(true){char buffer[1024];struct sockaddr_in peer;socklen_t len= sizeof(peer);ssize_t n=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr* )&peer,&len);if(n>0){buffer[n] = 0;InetAddr addr(peer);//创建一个网络地址的类对象LOG(DEBUG, "get message from [%s:%d]: %s\n", addr.Ip().c_str(),addr.Port(),buffer);// 2. 我们要将server收到的数据,发回给对方,表示已接收sendto(_sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&peer, len);}}_isrunning = false;}
private:int _sockfd; //sock文件描述符uint16_t _port; //端口号bool _isrunning; //服务器是否启动
};

解释

在这里插入图片描述
利用socket函数创建socket编程接口,AF_INET表示IPv4,SOCK_DGRAM表示udp数据报套接字的;

在这里插入图片描述
INADDR_ANY: 调用bind()函数将套接字与一个特定的端口(以及可选的IP地址)绑定时,可以将IP地址设置为INADDR_ANY(其值通常为0,表示“任何地址”)。这样做的好处是,UDP服务器将能够接收来自任何网络接口的连接请求,而不仅仅是绑定时指定的那一个。

在这里插入图片描述
这样bind之后就能让IP地址与端口号和Socket编程接口联系起来,让接口 “有名有性” ;

在这里插入图片描述将接收的数据存储在buffer中,peer可以接收到发送端的地址信息;
只有n大于0,才表示接收到了具体数据;

在这里插入图片描述
将接收到的数据信息,可以经过一定的处理,然后发送回客户端,这里中间没有经过处理,只是将接收到的信息直接反馈给客户端而已;也就是将buffer中的内容发送到客户端中;

InetAddr.hpp

InetAddr类:将包含主机上一切有关地址的信息;
在这里插入图片描述

代码

#pragma once#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
using namespace std;class InetAddr
{
public:InetAddr(const struct sockaddr_in& addr):_addr(addr){GetAddress(&_ip,&_port);}string Ip(){return _ip;}uint16_t Port(){return _port;}~InetAddr(){}
private://通过已知的sockaddr信息获取对应的ip地址信息和端口号void GetAddress(string* ip,uint16_t* port){*port=ntohs(_addr.sin_port);*ip=inet_ntoa(_addr.sin_addr);}struct sockaddr_in _addr; //sockaddr的信息string _ip; //IP地址uint16_t _port; //端口号
};

main.cc

初始化服务端并启动服务端

#include<iostream>
#include<memory>
using namespace std;
#include"UdpServer.hpp"void Usage(string proc)
{cout<<"Usage:\n\t"<<proc<<" local_port\n"<<endl;
}//示例: ./main.cc 8888
int main(int argc,char* argv[])
{if(argc!=2){Usage(argv[0]);exit(USAGE_ERROR);}EnableScreen();//打印到屏幕uint16_t port = stoi(argv[1]); //获取对应的端口号unique_ptr<UdpServer> usvr=std::make_unique<UdpServer>(port);//智能指针usvr->InitServer(); // 初始化服务端usvr->Start(); // 启动服务端return 0;
}

在这里插入图片描述
通过智能指针的性质,创建一个指向UdpServer类对象的指针,能够在周期结束时自动回收对应的智能指针;

UdpClient.cc

作为客户端能够不断给服务端发送数据并接收对应数据,构建Socket编程接口与上面一致。

#include<iostream>
using namespace std;
#include<string>
#include<cstring>
#include<cstdlib>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>void Usage(string proc)
{cout<<"Usage:\n\t"<<proc<< " serverip serverport\n"<<endl;
}//示例: ./UdpClient.cc 127.0.0.1 8080
int main(int argc,char* argv[])
{if(argc!=3){Usage(argv[0]);exit(1);}string serverip=argv[1];//服务端ipuint16_t serverport=stoi(argv[2]);//服务端端口号//创建socketint sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){cerr<<"socket error"<<endl;}//构建目标主机socket信息struct sockaddr_in server;memset(&server,0,sizeof(server));server.sin_family=AF_INET;server.sin_port=htons(serverport);server.sin_addr.s_addr=inet_addr(serverip.c_str());string message;while(true){cout<<"Please Enter# ";getline(cin,message);//获取输入的一行字符串,空格亦可接收,输入到message中sendto(sockfd,message.c_str(),message.size(),0,(struct sockaddr *)&server,sizeof(server));//发送给服务端struct sockaddr_in peer;socklen_t len = sizeof(peer);char buffer[1024];//接收存放数据ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&peer, &len);//接收服务端发送数据if(n > 0){buffer[n] = 0;std::cout << "server echo# " << buffer << std::endl;}}
}

127.0.0.1

127.0.0.1 是一个特殊的IP地址,被称为回环地址(Loopback Address)。在IPv4网络中,它被用于指向本机(即运行代码的计算机)。当你尝试访问 127.0.0.1 上的某个端口时,你的操作系统会识别这是一个内部请求,并将该请求直接路由回本机上的相应服务,而不会通过网络发送到外部。

这种机制使得开发者能够在本地测试网络服务,而无需担心外部网络的影响。

验证

在这里插入图片描述
在这里插入图片描述
我们可以通过命令行netstat来进行查询对应网络接口:

netstat(网络统计)命令是Linux系统中用于显示网络连接、路由表、接口统计、伪装连接和多播成员等网络相关信息的强大工具。

在这里插入图片描述

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

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

相关文章

算法:[递归/搜索/回溯]二叉树的深搜

目录 题目一&#xff1a;计算布尔二叉树的值 题目二&#xff1a;求根节点到叶节点数字之和 题目三&#xff1a;二叉树剪枝 题目四&#xff1a;验证二叉搜索树 题目五&#xff1a;二叉搜索树中第k小的元素 题目六&#xff1a;二叉树的所有路径 题目一&#xff1a;计算布尔…

前端调接口拿到数据之后,复制文本

一、使用navigator.clipboard对获取的内容进行复制。 需要注意navigator.clipboard使用的条件是&#xff1a; 1.通过 HTTPS 协议访问的页面 2.本地开发服务器上的页面&#xff0c;即 URL 为 http://localhost。经测试http://127.0.0.1&#xff0c;这个是不能使用的。 3.直接…

【C语言】宏定义常量加 ; 的错误

我在使用宏定义常量定义二维数组的时候&#xff0c;编译器报错&#xff1a;应输入“]”&#xff0c;如下&#xff1a; 原因是宏定义不是C语言规定的语句&#xff0c;它的结尾不加 ; 。在上图的 int mine[EASY_ROWS][EASY_COLS]; 中&#xff0c;把 EASY_ROWS 替换为了 9;2; &…

【VUE3】vue3 面试知识点

1. Vue 3 相比 Vue 2 的主要改进 Composition API&#xff1a;引入了一套基于函数的 API&#xff0c;允许以更灵活和可复用的方式组织组件逻辑。性能提升&#xff1a;通过改进虚拟 DOM 的算法和底层架构&#xff0c;实现了更快的渲染速度和更低的内存使用率。TypeScript 支持&…

【秋招笔试题】小明的美食

解析&#xff1a;思维题。由于需要互不相同&#xff0c;每次操作取重复的值与最大值相加即可&#xff0c;这样即可保证相加后不会新增重复的值。因此统计重复值即可。 #include <iostream> #include <algorithm>using namespace std; const int maxn 1e5 5; int…

大模型算法面试题(十一)

本系列收纳各种大模型面试题及答案。 1、说一下目前主流或前沿的预训练模型&#xff0c;包括nlp&#xff08;百度ERNIE3.0&#xff0c;华为NEZHA&#xff0c;openAI gpt-3&#xff0c;nvidia MegatronLM&#xff0c;macrosoft T5&#xff09;和cv&#xff08;我只知道CLIP&…

wordpress主题Typecho仿百度响应式主题Xaink

wordpress主题Typecho仿百度响应式主题Xaink 新闻类型博客主题&#xff0c;简洁好看&#xff0c;适合资讯类、快讯类、新闻类博客建站&#xff0c;响应式设计&#xff0c;支持明亮和黑暗模式 直接下载 zip 源码->解压后移动到 Typecho 主题目录->改名为xaink->启用

内衣洗衣机和手洗哪个干净?推荐五款品质优良精品

在日常生活中&#xff0c;内衣洗衣机已成为现代家庭必备的重要家电之一。选择一款耐用、质量优秀的内衣洗衣机&#xff0c;不仅可以减少洗衣负担&#xff0c;还能提供高效的洗涤效果。然而&#xff0c;市场上众多内衣洗衣机品牌琳琅满目&#xff0c;让我们往往难以选择。那么&a…

实时捕获数据库变更

1.CDC概述 CDC 的全称是 Change Data Capture &#xff0c;在广义的概念上&#xff0c;只要能捕获数据变更的技术&#xff0c;我们都可以称为 CDC 。我们目前通常描述的CDC 技术主要面向数据库的变更&#xff0c;是一种用于捕获数据库中数据变更的技术&#xff0c;CDC 技术应用…

pytorch backbone

1 简介 在PyTorch深度学习中&#xff0c;预训练backbone&#xff08;骨干网络&#xff09;是一个常见的做法&#xff0c;特别是在处理图像识别、目标检测、图像分割等任务时。预训练backbone通常是指在大型数据集&#xff08;如ImageNet&#xff09;上预先训练好的卷积神经网络…

基于Flink SQL CDC的实时数据同步

基于Flink SQL CDC&#xff08;Change Data Capture&#xff09;的实时数据同步是一种高效的数据处理方案&#xff0c;它允许用户实时捕获数据库中的变更操作&#xff0c;并将这些变更以流的形式进行处理和同步到其他系统或数据库中。以下是关于基于Flink SQL CDC的实时数据同步…

Linux嵌入式学习——数据结构——队列

一、概念 1&#xff09;定义 是只允许在一端进行插入操作&#xff0c;而在另一端进行删除操作的线性表 队列 是一种 先进先出&#xff08;First In First Out&#xff09; 的线性表 线性表有顺序存储和链式存储&#xff0c;栈是线性表&#xff0c;所以有这两种存储方式 同样…

【在开发小程序的时候如何排查问题】

在开发小程序的时候如何排查问题 在最近开发小程序的时候&#xff0c;经常出现本地在浏览器中调试没有问题&#xff0c;但是一发布到预发环境就出现各种个样的问题 手机兼用性问题 有时候会出现苹果&#x1f34e;手机键盘弹出&#xff0c;导致ui界面高度出现异常边界问题&#…

使用PageHelper插件来分页查询

目录 一.什么是PageHelper&#xff1f; 二.PageHelper的实战操作&#xff1a; 1.导入PageHelper的相关依赖&#xff1a; 2.配置代码展示&#xff1a; 3.分页查询代码解析&#xff1a; 另外&#xff0c;肯定读者会好奇为什么能够自动动态拼接&#xff1f; 一.什么是PageH…

关于Static 误用问题,总是记不住

一、常规的 静态局部变量&#xff0c;静态成员变量和成员函数没啥疑问 二、全局变量问题。。。 * 如果在 C 文件中使用 static 修饰全局变量&#xff0c; * 它将限制变量的作用域在当前文件内。 * 这意味着其他文件无法直接访问或修改这个变量的值。 …

Arduino IDE界面和设置(基础知识)

Arduino IDE界面和设置&#xff08;基础知识&#xff09; 1-2 Arduino IDE界面和设置如何来正确选择Arduino开发板型号如何正确选择Arduino这个端口如何来保存一个Arduino程序Arduino ide 的界面功能按钮验证编译上传新建打开保存工作状态 1-2 Arduino IDE界面和设置 大家好这…

day00-系统重要文件

01.知识点回顾 1.resolv.conf dns的配置文件 [rootlinux ~]# vim /etc/resolv.conf [rootlinux ~]# nslookup www.baidu.com Server: 8.8.8.8 Address: 8.8.8.8#53Non-authoritative answer: www.baidu.com canonical name www.a.shifen.com. Name: www.a.shifen.com Addre…

MongoDB适合哪些人使用

MongoDB 是一款高性能、开源、无模式的文档型数据库&#xff0c;它使用 BSON&#xff08;Binary JSON&#xff09;作为其数据格式&#xff0c;这使得 MongoDB 非常适合于存储和查询复杂的数据结构。MongoDB 的灵活性、可扩展性和高性能特性吸引了多种类型的用户。以下是 MongoD…

如何穿透模糊,还原图片真实面貌

目录 图像清晰化的魔法棒&#xff1a;AI如何穿透模糊&#xff0c;还原图片真实面貌 前言 论文背景 论文思路 模型介绍 复现过程 演示视频 使用方式 本文所涉及所有资源均在传知代码平台可获取。 图像清晰化的魔法棒&#xff1a;AI如何穿透模糊&#xff0c;还原图片真实面貌 在我…

全网最最实用--模型高效推理:量化基础

文章目录 一、量化基础--计算机中数的表示1. 原码&#xff08;Sign-Magnitude&#xff09;2. 反码&#xff08;Ones Complement&#xff09;3. 补码&#xff08;Twos Complement&#xff09;4. 浮点数&#xff08;Floating Point&#xff09;a.常用的浮点数标准--IEEE 754(FP32…