当前位置: 首页 > news >正文

简单的Udp服务器

目录

  • 简单的UDP网络程序
    • 1.1 UdpServer.hpp
    • 1.2 UdpClient.cc
    • 1.3 main.cc
    • 1.4 makefile
    • 1.5 log.hpp

简单的UDP网络程序

1.1 UdpServer.hpp

#pragma once#include <iostream>
using namespace std;#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "log.hpp"
#include <strings.h>
#include <functional>
#include <cstring>
#include <unordered_map>const static int NUM = 1024;
const static string DEFAULT_IP = "0.0.0.0";
const static uint16_t DEFAULT_PORT=8080;using func_t=function<string(string)>;Log log;class UdpServer
{
public:UdpServer(func_t func,uint16_t port=DEFAULT_PORT,string ip = DEFAULT_IP): _ip(ip), _port(port), _sockid(-1),_func(func){}~UdpServer(){if (_sockid > 0){close(_sockid);}}void Init(){// 创建套接字_sockid = socket(AF_INET, SOCK_DGRAM, 0);if (_sockid < 0){log(Fatal, "socket failed");exit(2);}log(Info,"create socket successful, sockid:%d",_sockid);// 绑定struct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);//绑定任意地址,可以接收任意发送给该主机的信息,而不是绑定一个具体的IP地址local.sin_addr.s_addr = INADDR_ANY;if (bind(_sockid, (struct sockaddr *)&local, sizeof(local)) < 0){log(Fatal, "bind failed, errno:%d, error code:%s",errno,strerror(errno));exit(3);}log(Info, "Server bind successful");}//通过哈希表检查用户是否已经连上,如果没有就添加到连接的列表中void CheckUser(const struct sockaddr_in& client){string clientIp=inet_ntoa(client.sin_addr);auto it=_online_client.find(clientIp);if(it==_online_client.end()){_online_client.insert({clientIp,client});std::cout << "[" << clientIp << ":" << ntohs(client.sin_port) << "] add to online user." << std::endl;}}//广播给所有人,即给所有连上该服务器的人都发送这条信息,类似于我们的微信群,//自己发出的信息所有人都能看见void BroadCast(const string& info,const string& clientip,const uint16_t& clientport){for(const auto& it:_online_client){string message="client";message+='[';message+="clientip:";message+=clientip;message+=' ';message+="clientport";message+=":";message+=to_string(clientport);message+="]# ";message+=info;sendto(_sockid,message.c_str(),message.size(),0,(struct sockaddr*)(&it.second),sizeof(it.second));}}//启动服务器void Run(){struct sockaddr_in client;socklen_t len = sizeof(client);bzero(&client, sizeof(client));char buffer[NUM];bzero(buffer, sizeof(buffer));while (true){ssize_t s = recvfrom(_sockid, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&client, &len);if (s > 0){buffer[s] = '\0';//cout << "client# " << buffer << endl;//printf("client[ip:%d,port:%d]# \n",client.sin_addr.s_addr,client.sin_port);char* clientip=inet_ntoa(client.sin_addr);//检查CheckUser(client);cout << "client[ip:"<<clientip<<" port:"<<ntohs(client.sin_port)<<"]# " << buffer << endl;uint16_t clientport=ntohs(client.sin_port);//广播给所有人BroadCast(buffer,clientip,clientport);}else if(s==0){log(Warning,"client quit...");break;}else{log(Fatal,"recvfrom failed...");break;}//string ret=_func(buffer);//sendto(_sockid, ret.c_str(), ret.size(), 0, (struct sockaddr *)&client, len);}}private:string _ip;uint16_t _port;int _sockid;//回调函数func_t _func;//通过IP地址映射标识一个已经连上服务器的客户端unordered_map<string,struct sockaddr_in> _online_client;
};

1.2 UdpClient.cc


#include <iostream>
using namespace std;#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <pthread.h>
#include <cstring>//   重定向:2>/dev/pts/(1,2,3,4)//UdpClient.ccconst static int NUM = 1024;//客户端使用手册
void Usage(string argv)
{cout << "\n\t"<< "Usage:" << argv << " ServerIp ServerPort" << endl<<endl;
}struct ThreadData
{int sockid;struct sockaddr_in server;string ip;
};//读取信息
void* recver_message(void* argv)
{//线程分离pthread_detach(pthread_self());ThreadData* td=static_cast<ThreadData*>(argv);char buffer[4096];memset(buffer,0,sizeof(buffer));while(true){struct sockaddr_in t;socklen_t len=sizeof(t);ssize_t s=recvfrom(td->sockid,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&t,&len);string tip=inet_ntoa(t.sin_addr);if(s>0){buffer[s]='\0';// cout<<"server# "<<tmp<<endl;printf("server[ip:%s,port:%d]# %s\n",tip.c_str(),ntohs(t.sin_port),buffer);}}return nullptr;
}//发送信息
void * sender_message(void* argv)
{pthread_detach(pthread_self());ThreadData* td=static_cast<ThreadData*>(argv);std::string welcome = td->ip;welcome += " comming...";sendto(td->sockid, welcome.c_str(), welcome.size(), 0, (struct sockaddr *)&(td->server), sizeof(td->server));string buffer;while(true){cerr<<"Please Enter# ";getline(cin,buffer);sendto(td->sockid,buffer.c_str(),buffer.size(),0,(struct sockaddr*)(&(td->server)),sizeof(td->server));}return nullptr;
}int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}string ServerIp=argv[1];string str = argv[2];uint16_t ServerPort = (uint16_t)stoi(str.c_str());ThreadData td;//创建套接字int sockid=socket(AF_INET,SOCK_DGRAM,0);td.server.sin_family = AF_INET;td.server.sin_addr.s_addr=inet_addr(ServerIp.c_str());td.server.sin_port=htons(ServerPort);td.ip=ServerIp;td.sockid=sockid;socklen_t len=sizeof(td.server);pthread_t recver,sender;pthread_create(&recver,nullptr,recver_message,&td);pthread_create(&sender,nullptr,sender_message,&td);    while(true){sleep(1);}close(sockid);
}

1.3 main.cc

#include <iostream>
using namespace std;
#include <string>
#include "UdpServer.hpp"
#include <vector>
#include <memory>//服务器的启动方式
void Usage(string argv)
{cout << "\n\t"<< "Usage:" << argv << " ServerPort" << endl<< endl;
}string func(string s)
{return s + " already handled\n";
}//安全检查
bool SafeCheck(const string &cmd)
{//把客户端发过来的信息当作命令来解析,检查该信息是否合法vector<string> key_word = {"rm", "mv", "cp", "kill", "sudo", "unlink", "uninstall","yum", "top", "while"};for(const auto& s:key_word){auto pos = cmd.find(s);if(pos!=string::npos){return false;}}return true;
}//执行指令
string ExcuteCommand(string cmd)
{if (!SafeCheck(cmd)){return "bad man\n";}//popen函数会自己创建子进程,创建管道,让子进程执行cmd.c_str()命令,//并通过管道把执行cmd命令的结果读取到FILE*的结构体对象中FILE *p = popen(cmd.c_str(), "r");if (nullptr == p){perror("popen failed");exit(5);}string ret="\n";char buffer[4096];while (true){//把执行命令后的结果按行读取出来char *s = fgets(buffer, sizeof(buffer) - 1, p);if (nullptr == s){break;}ret += buffer;}pclose(p);return ret;
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);exit(1);}string str = argv[1];uint16_t ServerPort = (uint16_t)stoi(str.c_str());unique_ptr<UdpServer> svr(new UdpServer(func, ServerPort));svr->Init();svr->Run();return 0;
}

1.4 makefile

.PHONY:all
all:Client ServerClient:UdpClient.ccg++ -o $@ $^ -std=c++11 -lpthreadServer:main.ccg++ -o $@ $^ -std=c++11 -lpthread.PHONY:clean
clean:rm -f Client Server

1.5 log.hpp

#pragma once#include <iostream>
using namespace std;
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string>
#include <time.h>
#include <stdarg.h>// 日志等级
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4#define Screen 1
#define OneFile 2
//向多个文件打印
#define Classfile 3
#define SIZE 1024#define LogFile "log.txt"class Log
{
public:Log(){printMethod = Screen;path = "./log/";}void Enable(int mothod){printMethod = mothod;}string LevelToString(int level){switch (level){case Info:{return "Info";}case Debug:{return "Debug";}case Warning:{return "Warning";}case Error:{return "Error";}case Fatal:{return "Fatal";}default:{return "None";}}}void printlog(int level,const string& logtxt){switch(printMethod){case Screen:{cout<<logtxt<<endl;break;}case OneFile:{PrintOneFile(LogFile,logtxt);break;}case Classfile:{PrintClassfile(level,logtxt);break;}default:{break;}}}void PrintOneFile(const string& logname,const string& logtxt){string _logname=path+logname;int fd=open(_logname.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);if(fd<0){perror("open fail");return;}write(fd,logtxt.c_str(),logtxt.size());close(fd);}void PrintClassfile(int level,const string& logtxt){string filename=LogFile;filename+='.';filename+=LevelToString(level);PrintOneFile(filename,logtxt);}void operator()(int level,const char* format,...){time_t t=time(nullptr);struct tm* ctime=localtime(&t);char leftbuffer[SIZE];snprintf(leftbuffer,SIZE,"[%s][%d-%d-%d %d:%d:%d]",LevelToString(level).c_str(),ctime->tm_year+1900,ctime->tm_mon+1,ctime->tm_mday,ctime->tm_hour,ctime->tm_min,ctime->tm_sec);va_list s;va_start(s,format);char rightbuffer[SIZE]={0};vsnprintf(rightbuffer,SIZE,format,s);va_end(s);char logtxt[SIZE*2];snprintf(logtxt,sizeof(logtxt),"%s %s",leftbuffer,rightbuffer);printlog(level,logtxt);}~Log(){}private:// 打印方法int printMethod;string path;
};

相关文章:

简单的Udp服务器

目录 简单的UDP网络程序1.1 UdpServer.hpp1.2 UdpClient.cc1.3 main.cc1.4 makefile1.5 log.hpp 简单的UDP网络程序 1.1 UdpServer.hpp #pragma once#include <iostream> using namespace std;#include <unistd.h> #include <sys/types.h> #include <sy…...

【Linux进程间通信】用管道实现简单的进程池、命名管道

【Linux进程间通信】用管道实现简单的进程池、命名管道 目录 【Linux进程间通信】用管道实现简单的进程池、命名管道为什么要实现进程池&#xff1f;代码实现命名管道创建一个命名管道 理解命名管道匿名管道与命名管道的区别命名管道的打开规则 作者&#xff1a;爱写代码的刚子…...

Linux操作系统基础(九):Linux用户与权限

文章目录 Linux用户与权限 一、文件权限概述 二、终端命令&#xff1a;组管理 三、终端命令&#xff1a;用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…...

蓝桥杯——第 5 场 小白入门赛(c++详解!!!)

文章目录 1 十二生肖基本思路&#xff1a; 2 欢迎参加福建省大学生程序设计竞赛基本思路&#xff1a;代码&#xff1a; 3 匹配二元组的数量基本思路&#xff1a;代码: 4 元素交换基本思路&#xff1a;代码&#xff1a; 5 下棋的贝贝基本思路&#xff1a;代码&#xff1a; 6 方程…...

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量&#xff0c;叶节点满足&#xff0c;从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现&#xff0c;当不满足条件时直接返回。 到达叶节点后统计答案&#xff0c;用…...

797. 差分

Problem: 797. 差分 文章目录 思路解题方法复杂度Code 思路 这是一个差分数组的问题。差分数组的主要适用场景是频繁对原始数组的某一个区间进行增减操作。这种操作是区间修改操作&#xff0c;在这种操作下&#xff0c;差分数组只需要对区间的两个端点进行操作&#xff0c;时间…...

2024.2.5 vscode连不上虚拟机,始终waiting for server log

昨天还好好的&#xff0c;吃着火锅&#xff0c;做着毕设&#xff0c;突然就被vscode给劫了。 起初&#xff0c;哥们跟着网上教程有模有样地删除了安装包缓存&#xff0c;还删除了.vscode-server&#xff0c;发现没卵用&#xff0c;之前都是搜那个弹窗报错。 后来发现原来是vsco…...

CSS基础---新手入门级详解

CSS:层叠样式表 CSS&#xff08;Cascading Style Sheets,层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档添加样式&#xff08;字体、间距和颜色&#xff09;的计算机语言&#xff0c;css扩展名为.css。 实例: <!DOCTYPE html><html> <head><…...

Python中Pymysql库的常见用法和代码示例

关注B站可以观看更多实战教学视频&#xff1a;肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) pymysql是一个用于连接MySQL数据库的Python库&#xff0c;它允许你执行SQL查询并处理返回的结果。以下是pymysql库的一些常见用法和代码示例&#xff1a; 1. 安装…...

使用 WPF + Chrome 内核实现高稳定性的在线客服系统复合应用程序

对于在线客服与营销系统&#xff0c;客服端指的是后台提供服务的客服或营销人员&#xff0c;他们使用客服程序在后台观察网站的被访情况&#xff0c;开展营销活动或提供客户服务。在本篇文章中&#xff0c;我将详细介绍如何通过 WPF Chrome 内核的方式实现复合客服端应用程序。…...

fastapi mysql 开发restful 3

pip install mysql-connector-python pymysql 数据库链接 创建src目录&#xff0c;里面创建db.py 代码如下&#xff1a; # 导入mysql.connector模块&#xff0c;该模块提供了与MySQL数据库进行连接和交互的功能。 import mysql.connector # 定义一个函数get_db_connectio…...

【Uniapp uni-app学习与快速上手——详细讲解】

Uniapp uni-app学习与快速上手——详细讲解 1. 介绍2. Uni-app 学习资源3. 快速上手4. 开始第一个项目5. 调试和发布 1. 介绍 Uni-app 是一个使用 Vue.js 编写多端应用的前端框架。开发者可以编写一份代码&#xff0c;然后发布到iOS、Android、网页&#xff08;响应式&#xf…...

剑指offer——旋转数组的最小数字

目录 1. 题目描述2. 分析思路2.1 示例分析 3. 更完美的做法 1. 题目描述 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个递增排序的数组的一个旋转&#xff0c;输出旋转数组的最小元素。例如数组{3.4,5,1.2}为{1.2,3,4,5}的一个旋转&a…...

盘点数据可视化大屏焦点图十种样式

所谓焦点图就是大屏中居于中心位置的图&#xff0c;是视觉的中心&#xff0c;本位列举了十种焦点图样式供大家参考。 地球作为焦点图 图片来自网络 地图作为焦点图 图片来自网络 城市作为焦点图 图片来自网络 园区做焦点图 图片来自网络 建筑做焦点图 图片来自网络 生产线…...

问题 G: 老鼠和猫的交易

题目描述 小老鼠准备了M磅的猫粮&#xff0c;准备去和看守仓库的猫做交易&#xff0c;因为仓库里有小老鼠喜欢吃的五香豆。 仓库有N个房间&#xff1b; 第i个房间有J[i] 磅的五香豆&#xff0c;并且需要用F[i]磅的猫粮去交换&#xff1b; 老鼠不必交换该房间所有的五香豆&…...

HiveSQL——借助聚合函数与case when行转列

一、条件函数 if 条件函数 if函数是最常用到的条件函数&#xff0c;其写法是if(xn,a,b), xn代表判断条件&#xff0c;如果xn时&#xff0c;那么结果返回a ,否则返回b。 selectif(age < 25 or age is null, 25岁以下, 25岁以上) as age_cnt,count(1) as number from table…...

冒泡排序,判断回文,以及12-24小时制

6-7 定义函数&#xff0c;完成冒泡排序算法。 本题定义一个冒泡排序算法的函数&#xff0c;调用函数后实现数组的升序排序&#xff0c;其数组长度为任意长度。 函数接口定义&#xff1a; 在这里描述函数接口。例如&#xff1a; void sort(int arr[],int n); 在这里解释接口…...

【Vue】computed与watch

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Vue⛺️稳重求进&#xff0c;晒太阳 计算属性 概念&#xff1a;基于现有的数据&#xff0c;计算出来新的属性&#xff0c;依赖的数据变化&#xff0c;自动重新计算 语法&#xff1a; 声明…...

探索设计模式的魅力:捕捉变化的风-用观察者模式提升用户体验

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 一、引言 核心概念 应用场景 可以解决的问题 二、场景案例 2.1 不用设计模式实现 2.2 存在问题 2.3 使用设计模式实现 2.4 成功克服 三、工作原理 3.1 结构图和说明 3.2 工作原理详解 3.3 实现步骤 四、 优…...

SpringCloud-高级篇(十九)

我们已经学过使用 SpringAMQP去收和发消息&#xff0c;但是发和收消息是只是MQ最基本的功能了&#xff0c;在收发消息的过程中&#xff0c;会有很多的问题需要去解决&#xff0c;下面需要学习rabbitMQ的高级特性去解决 死信交换机&#xff1a;这个可以帮助我们实现消息的延迟的…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

快速排序算法改进:随机快排-荷兰国旗划分详解

随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...

表单设计器拖拽对象时添加属性

背景&#xff1a;因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...