简单的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进程间通信】用管道实现简单的进程池、命名管道为什么要实现进程池?代码实现命名管道创建一个命名管道 理解命名管道匿名管道与命名管道的区别命名管道的打开规则 作者:爱写代码的刚子…...

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

蓝桥杯——第 5 场 小白入门赛(c++详解!!!)
文章目录 1 十二生肖基本思路: 2 欢迎参加福建省大学生程序设计竞赛基本思路:代码: 3 匹配二元组的数量基本思路:代码: 4 元素交换基本思路:代码: 5 下棋的贝贝基本思路:代码: 6 方程…...

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)
文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量,叶节点满足,从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现,当不满足条件时直接返回。 到达叶节点后统计答案,用…...
797. 差分
Problem: 797. 差分 文章目录 思路解题方法复杂度Code 思路 这是一个差分数组的问题。差分数组的主要适用场景是频繁对原始数组的某一个区间进行增减操作。这种操作是区间修改操作,在这种操作下,差分数组只需要对区间的两个端点进行操作,时间…...

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

CSS基础---新手入门级详解
CSS:层叠样式表 CSS(Cascading Style Sheets,层叠样式表),是一种用来为结构化文档添加样式(字体、间距和颜色)的计算机语言,css扩展名为.css。 实例: <!DOCTYPE html><html> <head><…...
Python中Pymysql库的常见用法和代码示例
关注B站可以观看更多实战教学视频:肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) pymysql是一个用于连接MySQL数据库的Python库,它允许你执行SQL查询并处理返回的结果。以下是pymysql库的一些常见用法和代码示例: 1. 安装…...

使用 WPF + Chrome 内核实现高稳定性的在线客服系统复合应用程序
对于在线客服与营销系统,客服端指的是后台提供服务的客服或营销人员,他们使用客服程序在后台观察网站的被访情况,开展营销活动或提供客户服务。在本篇文章中,我将详细介绍如何通过 WPF Chrome 内核的方式实现复合客服端应用程序。…...
fastapi mysql 开发restful 3
pip install mysql-connector-python pymysql 数据库链接 创建src目录,里面创建db.py 代码如下: # 导入mysql.connector模块,该模块提供了与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 编写多端应用的前端框架。开发者可以编写一份代码,然后发布到iOS、Android、网页(响应式…...

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

盘点数据可视化大屏焦点图十种样式
所谓焦点图就是大屏中居于中心位置的图,是视觉的中心,本位列举了十种焦点图样式供大家参考。 地球作为焦点图 图片来自网络 地图作为焦点图 图片来自网络 城市作为焦点图 图片来自网络 园区做焦点图 图片来自网络 建筑做焦点图 图片来自网络 生产线…...
问题 G: 老鼠和猫的交易
题目描述 小老鼠准备了M磅的猫粮,准备去和看守仓库的猫做交易,因为仓库里有小老鼠喜欢吃的五香豆。 仓库有N个房间; 第i个房间有J[i] 磅的五香豆,并且需要用F[i]磅的猫粮去交换; 老鼠不必交换该房间所有的五香豆&…...

HiveSQL——借助聚合函数与case when行转列
一、条件函数 if 条件函数 if函数是最常用到的条件函数,其写法是if(xn,a,b), xn代表判断条件,如果xn时,那么结果返回a ,否则返回b。 selectif(age < 25 or age is null, 25岁以下, 25岁以上) as age_cnt,count(1) as number from table…...
冒泡排序,判断回文,以及12-24小时制
6-7 定义函数,完成冒泡排序算法。 本题定义一个冒泡排序算法的函数,调用函数后实现数组的升序排序,其数组长度为任意长度。 函数接口定义: 在这里描述函数接口。例如: void sort(int arr[],int n); 在这里解释接口…...

【Vue】computed与watch
📝个人主页:五敷有你 🔥系列专栏:Vue⛺️稳重求进,晒太阳 计算属性 概念:基于现有的数据,计算出来新的属性,依赖的数据变化,自动重新计算 语法: 声明…...

探索设计模式的魅力:捕捉变化的风-用观察者模式提升用户体验
设计模式专栏:http://t.csdnimg.cn/U54zu 目录 一、引言 核心概念 应用场景 可以解决的问题 二、场景案例 2.1 不用设计模式实现 2.2 存在问题 2.3 使用设计模式实现 2.4 成功克服 三、工作原理 3.1 结构图和说明 3.2 工作原理详解 3.3 实现步骤 四、 优…...

SpringCloud-高级篇(十九)
我们已经学过使用 SpringAMQP去收和发消息,但是发和收消息是只是MQ最基本的功能了,在收发消息的过程中,会有很多的问题需要去解决,下面需要学习rabbitMQ的高级特性去解决 死信交换机:这个可以帮助我们实现消息的延迟的…...
Vue项目PDF目录功能集成【一】——方案深度思考
文章目录 项目背景一、方案一:数据透传 外部开发模式二、方案二:内置组件 黑盒模式三、方案三:激活官方实现 可控定制总结 项目背景 本项目是Vue 3 项目,需要使用文件预览组件(pdfjs 当前是作为sdk二次封装引入&am…...
PHP文件读取漏洞全面剖析:触发点与利用技术
PHP文件读取漏洞全面剖析:触发点与利用技术 引言 PHP作为Web开发中最流行的语言之一,其文件操作功能强大但也暗藏风险。文件读取漏洞是PHP应用中最常见的安全问题之一,攻击者利用这些漏洞可以读取服务器敏感文件,甚至实现远程代…...

极昆仑智慧与数元灵科技达成战略合作
近日,北京极昆仑智慧科技有限公司与北京数元灵科技有限公司正式签署产品级融合战略合作协议,双方将围绕 "AIBI商业智能分析" " Hybrid RAG 大模型问答" 等核心大模型应用,实现技术架构与业务场景的深度集成,…...

基于fpga的疲劳驾驶检测
基于fpga的疲劳驾驶检测 前言一、系统硬件设计二、系统软件设计系统上板实验测试 前言 代码基于网络大佬代码进行修改的。限制性比较大,不太灵活,当个本科毕业设计还是够的。 基于FPGA的疲劳检测模块硬件设计以FPGA核心控制模块为中心,通过…...

SQL导出Excel支持正则脱敏
SQL to Excel Exporter 源码功能特性核心功能性能优化安全特性 快速开始环境要求安装运行 API 使用说明1. 执行SQL并导出Excel2. 下载导出文件3. 获取统计信息4. 清理过期文件 数据脱敏配置支持的脱敏类型脱敏规则配置示例 配置说明应用配置数据库配置 测试运行单元测试运行集成…...

【11408学习记录】考研写作双核引擎:感谢信+建议信复合结构高分模板(附16年真题精讲)
感谢信建议信 英语写作2016年考研英语(二)真题小作文题目分析写作思路第一段第二段锦囊妙句9:锦囊妙句12:锦囊妙句13:锦囊妙句18: 第三段 妙句成文 每日一句词汇第一步:找谓语第二步:…...

虚拟机时间同步
一、常见同步方式 常见的虚拟机同步方式有给虚拟机配置ntp、或者用平台提供的agent对时与虚拟机所在的宿主机。第一种依赖网络、第二种依赖平台的agent这个三方工具。 二、利用ptp_kvm.ko来直接和宿主机同步时间 关键组件 ptp_kvm驱动、chrony。 PTP_KVM同步原理 |--------…...

UOS 20 Pro为国际版WPS设置中文菜单
UOS 20 Pro为国际版WPS设置中文菜单 查看UOS操作系统系统安装国际版wps并汉化方法1:下载zh_CN.tar.gz语言包方法2:手动从国内版wps12的包中提取中文菜单解压国内版wps的包 复制中文语言包到wps国际版目录下安装Windows字体 安装开源office 查看UOS操作系统系统 # 查…...
stm32——UART和USART
串口通信协议UART和USART 1. UART与USART协议详解 特性UART (Universal Asynchronous Receiver/Transmitter)USART (Universal Synchronous Asynchronous Receiver/Transmitter)全称通用异步收发器通用同步/异步收发器同步/异步异步:不共享时钟,数据通过…...
深入理解汇编语言中的顺序与分支结构
本文将结合Visual Studio环境配置、顺序结构编程和分支结构实现,全面解析汇编语言中的核心编程概念。通过实际案例演示无符号/有符号数处理、分段函数实现和逻辑表达式短路计算等关键技术。 一、汇编环境配置回顾(Win32MASM) 在Visual Studi…...