【Linux】socket网络编程之UDP

【Linux】socket网络编程之UDP
在这里插入图片描述

个人主页~


socket网络编程UDP

一、必备接口

1、接收数据

recvfrom函数用于从套接字接收数据

#include<sys/socket.h>ssize_trecvfrom(int sockfd,void*buf,size_t len,int flags,structsockaddr*src_addr,socklen_t*addrlen);

返回值:返回正数表示成功接收到的数据字节数,返回0表示对方已经关闭了连接(对于TCP),返回-1表示发生错误
sockfd:指定从哪个套接字接收数据
buf:指向一个缓冲区,用于存储接收到的数据
len:指定buf的最大长度
flags:设置接收数据的标志,无标志一般设为0,在这里可以设置非阻塞模式
src_addr:用于存储发送方的地址信息,输出型参数
addrlen:用于指定src_addr结构体的长度,输入输出型参数,在调用 recvfrom 函数之前,需要将其初始化为 src_addr 结构体的最大长度,函数返回时,addrlen 会被更新为实际存储在 src_addr 中的地址信息的长度

2、发送数据

sendto函数用于在无连接的套接字(如 UDP 套接字)上发送数据

#include<sys/socket.h>ssize_tsendto(int sockfd,constvoid*buf,size_t len,int flags,conststructsockaddr*dest_addr,socklen_t addrlen);

返回值:返回正数表示成功发送的数据字节数,返回-1表示发送过程中出现错误
sockfd:指定通过哪个套接字发送数据
buf:指向要发送的数据的缓冲区
len:表示要发送的数据的长度(以字节为单位),即 buf 缓冲区中实际要发送的数据的字节数
flags:设置发送数据的标志,无标志一般设为0,在这里可以设置非阻塞模式
dest_addr:该结构体包含了目标地址的信息
addrlen:表示dest_addr结构体的长度(以字节为单位)

二、实现UDP网络编程

1、服务器

(一)UdpServer.hpp

#pragmaonce#include<iostream>#include<string>#include<strings.h>#include<cstring>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<functional>#include<unistd.h>// 下面两行都是代表着定义一个类似函数指针的变量func_t,参数和返回值都是string// using func_t = std::function<std::string(const std::string&)>;typedef std::function<std::string(const std::string&)> func_t;//枚举错误类型enum{ SOCKET_ERR=1, BIND_ERR };//定义端口号和ip地址uint16_t defaultport =8080; std::string defaultip ="0.0.0.0";//size用来定义缓冲区大小constint size =1024;classUdpServer{public:UdpServer(constuint16_t&port = defaultport,const std::string &ip = defaultip):sockfd_(0),port_(port),ip_(ip),isrunning_(false){}voidInit(){// 创建udp socket sockfd_ =socket(AF_INET, SOCK_DGRAM,0);if(sockfd_ <0){exit(SOCKET_ERR);}// 定义一个local存储本地地址structsockaddr_in local;//bzero的作用就是将local结构体清零bzero(&local,sizeof(local));//将local的前两个字节也就是它的地址族为AF_INET local.sin_family = AF_INET;//保证我们的端口号是网络字节序列,因为该端口号是要给对方发送的 local.sin_port =htons(port_);//inet_addr函数将ip_转换为in_addr_t类型的IP地址,并存储在local.sin_addr.s_addr local.sin_addr.s_addr =inet_addr(ip_.c_str());//绑定sockfd_到本地地址local上,失败则退出if(bind(sockfd_,(conststructsockaddr*)&local,sizeof(local))<0){exit(BIND_ERR);}}voidRun(func_t func)// 对代码进行分层{//设置服务器开始运行标志 isrunning_ =true;//定义缓冲区存放接收到的数据char inbuffer[size];while(isrunning_){//定义client结构体存储客户端的地址信息structsockaddr_in client; socklen_t len =sizeof(client);//获取客户端信息 ssize_t n =recvfrom(sockfd_, inbuffer,sizeof(inbuffer)-1,0,(structsockaddr*)&client,&len);if(n <0){continue;}//在最后添加字符串描述符'\0' inbuffer[n]=0;//将所有的信息通过func函数处理为echo_string std::string info = inbuffer; std::string echo_string =func(info);//将处理完后的数据发送到客户端sendto(sockfd_, echo_string.c_str(), echo_string.size(),0,(const sockaddr*)&client, len);}}//析构,sockfd_本质上是一个文件描述符一样的东西,用close可以关闭~UdpServer(){if(sockfd_>0)close(sockfd_);}private:int sockfd_;// 网路文件描述符 std::string ip_;// 任意地址bind 0uint16_t port_;// 表明服务器进程的端口号bool isrunning_;// 服务器运行状态};

(二)main.cpp

#include"UdpServer.hpp"#include<memory>#include<cstdio>// 端口号一般是可以随便定义的,但是[0,1023]范围内的端口号一般都是有固定的应用层协议的//所以我们都用1024+的端口号//输入小于1024的端口号就提示重输voidUsage(std::string proc){ std::cout <<"\n\rUsage: "<< proc <<" port[1024+]\n"<< std::endl;}//该函数用于处理接收到的消息,将消息添加到固定的前缀 "Server get a message: " 后面//并将结果输出到控制台 std::string Handler(const std::string &str){ std::string res ="Server get a message: "; res += str; std::cout << res << std::endl;return res;}//该函数用于执行客户端发送的命令,并将命令执行的结果返回给 UDP 服务器//从而实现服务器与客户端之间的交互,让客户端可以在服务器端执行命令并获取结果 std::string ExcuteCommand(const std::string &cmd){ FILE *fp =popen(cmd.c_str(),"r");if(nullptr== fp){perror("popen");return"error";} std::string result;char buffer[4096];while(true){char*ok =fgets(buffer,sizeof(buffer), fp);if(ok ==nullptr)break; result += buffer;}pclose(fp);return result;}// ./udpserver portintmain(int argc,char*argv[]){//在命令行中只带一个参,多带参和少带参都要执行Usageif(argc !=2){Usage(argv[0]);exit(0);}uint16_t port = std::stoi(argv[1]);//智能指针管理 UdpServer 对象的生命周期,确保对象在不再使用时自动释放内存 std::unique_ptr<UdpServer>svr(newUdpServer(port));//初始化并启动服务器 svr->Init(); svr->Run(ExcuteCommand);return0;}

2、客户端

UdpClient.cpp

#include<iostream>#include<cstdlib>#include<unistd.h>#include<strings.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>usingnamespace std;voidUsage(std::string proc){ std::cout <<"\n\rUsage: "<< proc <<" serverip serverport\n"<< std::endl;}intmain(int argc,char*argv[]){//命令行参数不为三个就打印提示信息if(argc !=3){Usage(argv[0]);exit(0);}//获取服务器端口号和服务器ip std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);//下面似曾相识呢,和上面服务器的解释一致structsockaddr_in server;bzero(&server,sizeof(server)); server.sin_family = AF_INET; server.sin_port =htons(serverport); server.sin_addr.s_addr =inet_addr(serverip.c_str()); socklen_t len =sizeof(server);int sockfd =socket(AF_INET, SOCK_DGRAM,0);if(sockfd <0){ cout <<"socker error"<< endl;return1;}//客户端套接字实际上也需要绑定,但通常不需要用户显式地进行绑定//操作系统会在客户端首次发送数据时自动为其分配一个可用的端口号进行绑定 string message;char buffer[1024];while(true){ cout <<"Please Enter@ ";getline(cin, message);//将消息发送到服务器sendto(sockfd, message.c_str(), message.size(),0,(structsockaddr*)&server, len);//接收信息并打印structsockaddr_in temp; socklen_t len =sizeof(temp); ssize_t s =recvfrom(sockfd, buffer,1023,0,(structsockaddr*)&temp,&len);if(s >0){ buffer[s]=0; cout << buffer << endl;}}close(sockfd);return0;}

最终我们实现的就是一个客户端可以通过指令操控服务器,然后将服务器应该输出的结果打印到客户端

在这里插入图片描述

今日分享就到这里了~

在这里插入图片描述

Read more

【Python】【数据分析】Python 数据分析与可视化:全面指南

【Python】【数据分析】Python 数据分析与可视化:全面指南

目录 * 1. 环境准备 * 2. 数据处理与清洗 * 2.1 导入数据 * 2.2 数据清洗 * 示例:处理缺失值 * 示例:处理异常值 * 2.3 数据转换 * 3. 数据分析 * 3.1 描述性统计 * 3.2 分组分析 * 示例:按年龄分组计算工资的平均值 * 3.3 时间序列分析 * 4. 数据可视化 * 4.1 基本绘图 * 示例:柱状图 * 4.2 使用 Seaborn 绘制图表 * 示例:箱型图 * 4.3 高级可视化技巧 * 示例:热力图

By Ne0inhk

08 Python 数据分析:学生画像匹配与相似度计算

Python 数据分析:学生画像匹配与相似度计算 适合人群:Python 初学者 / 数据分析入门 / 推荐系统基础学习者 / 教学案例分享 在数据分析和机器学习中,我们经常会遇到这样的问题: * 如何判断两个学生的学习习惯是否相似? * 如何衡量两个商品是不是“同类竞品”? * 为什么推荐系统能给你推送“你可能喜欢”的内容? * 两段文本内容相似,应该怎么用数据来表示? 这些问题,归根到底,都指向一个核心概念: 相似性度量 本文将通过“学生画像匹配”和“课程评价文本分析”两个小案例,带你理解下面几个非常常用的概念: * 欧氏距离(Euclidean Distance) * 曼哈顿距离(Manhattan Distance) * 余弦相似度(Cosine Similarity) 并结合 Python 完成简单实战。 一、案例引入:谁和你最像? 假设我们想根据学生的学习数据,寻找“和你最相似的同学”。 比如现在有三位学生的成绩数据: 学生数学英语A8085B8288C6070 问题来了:

By Ne0inhk
【Python基础】(五)Python 库使用全攻略:从标准库到第三方库,让开发效率翻倍

【Python基础】(五)Python 库使用全攻略:从标准库到第三方库,让开发效率翻倍

目录 编辑 前言 一、Python 库的核心认知:什么是库?为什么要用库? 1.1 库的本质:现成的 "代码工具箱" 1.2 库的分类:标准库 vs 第三方库 (1)标准库:Python 自带的 "基础工具箱" (2)第三方库:全球开发者共建的 "扩展工具箱" 1.3 使用库的核心优势:效率翻倍的关键 二、标准库实战:内置工具的高效用法 2.1 日期时间处理:datetime库(计算日期差、格式转换) 实战需求:计算你和心爱的人认识多少天 扩展用法:

By Ne0inhk
python通过调用海康SDK打开工业相机(全流程)

python通过调用海康SDK打开工业相机(全流程)

首先打开海康机器人-机器视觉-下载中心 下载最新版的 MVS 安装后打开目录找到 ...\MVS\Development\Samples\Python 将MvImport内所有文件拷贝至工作目录 然后到 C:\Program Files (x86)\Common Files\MVS\Runtime 找到适合自己系统的版本,将整个文件夹拷贝至工作目录,并重命名为lib,方便后期移植 完成上述操作后,工作目录是这样的: 打开MvCameraControl_class.py 找到 由于python3.8往后的版本导入动态链接库的机制发生了改变,因此这里时常会导入失败(2025-4-5) 因此需要更改为 *动态链接库的位置在刚刚更改名字的lib文件夹内,需根据实际情况做更改* 创建一个新的py文件(我的叫HKCamera.py)用于创建相机类,方便进行相机任务 在这个新的py文件中,创建一个类,用于创建句柄、开启流等操作 class Camera: #初始化 def __init__(self)

By Ne0inhk