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系统中用于显示网络连接、路由表、接口统计、伪装连接和多播成员等网络相关信息的强大工具。
相关文章:

Linux--Socket编程UDP
前文:Socket套接字编程 UDP协议特点 无连接:UDP在发送数据之前不需要建立连接,减少了开销和发送数据之前的时延。尽最大努力交付:UDP不保证可靠交付,主机不需要维持复杂的连接状态表。面向报文:UDP对应用层…...

《javaEE篇》--单例模式详解
目录 单例模式 饿汉模式 懒汉模式 懒汉模式(优化) 指令重排序 总结 单例模式 单例模式属于一种设计模式,设计模式就好比是一种固定代码套路类似于棋谱,是由前人总结并且记录下来我们可以直接使用的代码设计思路。 单例模式就是,在有…...
Java核心 - Lambda表达式详解与应用示例
作者:逍遥Sean 简介:一个主修Java的Web网站\游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有疑问和建议,请私信或评论留言! 前言 Lambda表达式是…...

算法通关:006_1二分查找
二分查找 查找一个数组里面是否存在num主要代码运行结果 详细写法自动生成数组和num,利用对数器查看二分代码是否正确 查找一个数组里面是否存在num 主要代码 /*** Author: ggdpzhk* CreateTime: 2024-07-27*/ public class cg {//二分查找public static boolean …...

总结一些vue3小知识3
总结一些vue3小知识1:http://t.csdnimg.cn/C5vER 总结一些vue3小知识2:http://t.csdnimg.cn/sscid 1.限制时间选择器只能选择后面的日期 说明:disabled-date属性是一个用来判断该日期是否被禁用的函数,接受一个 Date 对象作为参…...

JAVAWeb实战(前端篇)
项目实战一 0.项目结构 1.创建vue3项目,并导入所需的依赖 npm install vue-router npm install axios npm install pinia npm install vue 2.定义路由,axios,pinia相关的对象 文件(.js) 2.1路由(.js) import {cre…...

axios请求大全
本文讲解axios封装方式以及针对各种后台接口的请求方式 axios的介绍和基础配置可以看这个文档: 起步 | Axios中文文档 | Axios中文网 axios的封装 axios封装的重点有三个,一是设置全局config,比如请求的基础路径,超时时间等,第二点是在每次…...

C# 简单的单元测试
文章目录 前言参考文档新建控制台项目新建测试项目添加引用添加测试方法测试结果(有错误)测试结果,通过正规的方法抛出异常 总结 前言 听说复杂的项目最好都要单元测试一下。我这里也试试单元测试这个功能。到时候调试起来也方便。 参考文档 C# 单元测试…...

Linux中Mysql5.7主从架构(一主多从)配置教程
🏡作者主页:点击! 🐧Linux基础知识(初学):点击! 🐧Linux高级管理防护和群集专栏:点击! 🔐Linux中firewalld防火墙:点击! ⏰️创作…...

BACnet物联网关BL103:Modbus协议转BACnet/MSTP
随着物联网技术在楼宇自动化与暖通控制系统中的迅猛发展,构建一种既经济高效又高度可靠的协议转换物联网关成为了不可或缺的核心硬件组件。在此背景下,我们钡铼特别推荐一款主流的BAS(楼宇自动化系统)与BACnet物联网关——BL103&a…...
Go 语言条件变量 Cond
1.Cond 的使用方法 Go 标准库提供 Cond 同步原语的目的是为等待/通知场景下的并发操作提供支持。Cond 通常用于等待某个条件的一组 goroutine,当条件变为 true 时,其中一个或者所有的 goroutine 会被唤醒执行。 Cond 与某个条件相关,这个条件需要一组 goroutine 协作达到。当这…...

PostgreSQL 中如何重置序列值:将自增 ID 设定为特定值开始
我是从excel中将数据导入,然后再通过sql插入数据,就报错。 需要设置自增ID开始值 1、确定序列名称: 首先,需要找到与的增字段相关的序列名称。假设表名是 my_table 和自增字段是 id,可以使用以下查询来获取序列名称…...

Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示
Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 目录 Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 一、简单介绍 二、共享纹理 1、共享纹理的原理 2、共享纹理涉及到的关键知识点 3、什么可以实现共享 不能实现共享…...
Go语言的数据结构
数据结构 数组 支持多维数组,属于值类型,支持range遍历 例子:随机生成长度为10整数数组 package main import ("fmt""math/rand" ) // 赋值 随机获取100以内的整数 func RandomArrays() {var array [10]int //声明var…...
python_在sqlite中创建表并写入表头
python_在sqlite中创建表并写入表头 import sqlite3def write_title_to_sqlite(tableName,titleList,dataTypeGroupsList,database_path):conn sqlite3.connect(database_path)# 创建游标cursor conn.cursor()#MEMO 长文本#create_table_bodycreate_table_body "序号 …...

1.c#(winform)编程环境安装
目录 安装vs创建应用帮助查看器安装与使用( msdn) 安装vs 安装什么版本看个人心情,或者公司开发需求需要 而本栏全程使用vs2022进行开发c#,着重讲解winform桌面应用开发 使用***.net framework***开发 那先去官网安装企业版的vs…...

图中的最短环
2608. 图中的最短环 现有一个含 n 个顶点的 双向 图,每个顶点按从 0 到 n - 1 标记。图中的边由二维整数数组 edges 表示,其中 edges[i] [ui, vi] 表示顶点 ui 和 vi 之间存在一条边。每对顶点最多通过一条边连接,并且不存在与自身相连的顶…...
安装依赖 npm install idealTree:lib: sill idealTree buildDeps 卡着不动
我一直怀疑是网络问题,因为等了很久也能安装成功,就是时间比较长,直到现在完全受不了了,决定好好整治下这个问题! 1、执行命令 npm config get userconfig 查看配置文件所在位置,将其删除。 2、执行 n…...

LLMs之Llama 3.1:Llama 3.1的简介、安装和使用方法、案例应用之详细攻略
LLMs之Llama 3.1:Llama 3.1的简介、安装和使用方法、案例应用之详细攻略 导读:2024年7月23日,Meta重磅推出Llama 3.1。本篇文章主要提到了Meta推出的Llama 3.1自然语言生成模型。 背景和痛点 >> 过去开源的大型语言模型在能力和性能上一…...
如何实现一个大模型在回答问题时同时提供相关内容链接
通义生成 为了让大模型在回答问题时能够提供相关内容链接,通常采用的方法是结合检索增强生成(Retrieval-Augmented Generation, RAG)的技术。这种方法可以让大模型在生成答案的同时,从外部知识源中检索相关信息,并将这…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...