简单的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;
};

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

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

相关文章

17:数据库连接池与Servlet整合-Java Web

目录 17.1 引言17.2 数据库连接池原理及实现17.3 Servlet实现数据库操作17.4 数据库连接池与直连的区别总结17.5 数据库连接池的详细配置与优化17.6 Servlet结合JDBC操作数据库的进阶实践17.7 Spring框架下的数据库连接池与数据库操作17.8 应用场景总结 在构建高性能的Java Web…

Nginx反向代理WebSocket

Nginx 配置文件说明 在配置 Nginx 前先了熟悉一下配置文件的说明&#xff0c;方便更好的理解。 #全局设置 main # 运行用户 user www-data; # 启动进程,通常设置成和cpu的数量相等 worker_processes 1;# 全局错误日志及PID文件 error_log /var/log/nginx/error.log; pi…

VOL_偷懒记录!!

目录 前端1.记录 js如何获取当前时间(YY-MM-DD hh:mm:ss)2.记录 http请求3.记录(常用) 后端1.记录 前端 1.记录 js如何获取当前时间(YY-MM-DD hh:mm:ss) getCurrentTime() {const now new Date();return ${now.getFullYear()}-${(now.getMonth() 1).toString().padStart(2,…

java面试题:MySQL中的各种JOIN的区别

表关联是频率非常高的一种数据库操作&#xff0c;在MySQL中&#xff0c;这种JOIN操作有很多类型&#xff0c;包括内联接、左外连接、右外连接等等&#xff0c;而每种连接的含义都不一样&#xff0c;如果死记硬背&#xff0c;不仅很难记住&#xff0c;而且也容易搞混淆&#xff…

pytorch 利用Tensorboar记录训练过程loss变化

文章目录 1. LossHistory日志类定义2. LossHistory类的使用2.1 实例化LossHistory2.2 记录每个epoch的loss2.3 训练结束close掉SummaryWriter 3. 利用Tensorboard 可视化3.1 显示可视化效果 参考 利用Tensorboard记录训练过程中每个epoch的训练loss以及验证loss&#xff0c;便于…

前端工程化之:webpack3-5(css module)

目录 一、css module 1.思路 2.实现原理 3.如何应用样式 4.其他操作 &#xff08;1&#xff09;全局类名 &#xff08;2&#xff09;如何控制最终的类名 5.其他注意事项 一、css module 通过命名规范来限制类名太过死板&#xff0c;而 css in js 虽然足够灵活&…

Qt应用软件【协议篇】TCP示例

文章目录 TCP协议简介Qt中的TCP编程完整代码示例实际使用中的技巧实际使用中的注意事项TCP协议简介 TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。与UDP不同,TCP提供了数据包排序、重传机制、流量控制和拥塞控制,确保了数据传输的可靠性和顺序…

京东首页移动端-web实战

设置视口标签以及引入初始化样式 <link rel"stylesheet" href"./css/normalize.css"><link rel"stylesheet" href"./css/index.css"> body常用初始化样式 body {width: 100%;min-width: 320px;max-width: 640px;margin:…

作业2.5

第四章 堆与拷贝构造函数 一 、程序阅读题 1、给出下面程序输出结果。 #include <iostream.h> class example {int a; public: example(int b5){ab;} void print(){aa1;cout <<a<<"";} void print()const {cout<<a<<endl;} …

mysql 多数据源

依赖 <dependencies><!--mysql连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--多数据源--><dependency><g…

PostgreSQL开启wal日志归档模式

1.检查归档模式是否开启 postgres# show archive_mode;archive_mode --------------off (1 row)2.开启归档模式 ## 创建归档目录 mkdir -p /pgsql15.4/pg_arch## 配置归档相关参数 postgres# alter system set archive_modeon; ALTER SYSTEM postgres# alter system set arc…

P9240 [蓝桥杯 2023 省 B] 冶炼金属--2024蓝桥杯冲刺省一

点击跳转例题 思路&#xff1a;最开始读完题&#xff0c;我们知道求最小值最大&#xff0c;和最大值最小。是符合二分的性质的&#xff0c;但是我们再一思考可以发现这是简单的数学。 求每条记录的最小值&#xff1a;a/&#xff08;b1&#xff09;1。可以发现 a%b的情况下&…

【手写数据库toadb】虚拟文件描述符,连接表对象与物理文件的纽带,通过逻辑表找到物理文件的密码

22 存储管理抽象接口层 ​专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,…

VLM 系列——Llava1.6——论文解读

一、概述 1、是什么 Llava1.6 是llava1.5 的升级暂时还没有论文等&#xff0c;是一个多模态视觉-文本大语言模型&#xff0c;可以完成&#xff1a;图像描述、视觉问答、根据图片写代码&#xff08;HTML、JS、CSS&#xff09;&#xff0c;潜在可以完成单个目标的视觉定位、名画…

【go】gorm\xorm\ent事务处理

文章目录 1 gorm1.1 开启事务1.2 执行操作1.3 提交或回滚 2 xorm2.1 开启事务2.2 执行操作2.3 提交或回滚 3 ent3.1 开启事务3.2 执行操作3.3 提交或回滚 前言&#xff1a;本文介绍golang三种orm框架对数据库事务的操作 1 gorm Begin开启事务 tx *gorm.DB 1.1 开启事务 tx :…

Qt PCL学习(一):环境搭建

参考 (QT配置pcl)PCL1.12.1QT5.15.2vs2019cmake3.22.4vtk9.1.0visual studio2019Qt5.15.2PCL1.12.1vtk9.1.0cmake3.22.2 本博客用到的所有资源 版本一览&#xff1a;Visual Studio 2019 Qt 5.15.2 PCL 1.12.1 VTK 9.1.0https://pan.baidu.com/s/1xW7xCdR5QzgS1_d1NeIZpQ?pw…

计算机设计大赛 深度学习+opencv+python实现车道线检测 - 自动驾驶

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…

React+Antd+实现省、市区级联下拉多选组件

1、效果 是你要的效果&#xff0c;咱们继续往下看&#xff0c;搜索面板实现省市区下拉&#xff0c;原本有antd的Cascader组件&#xff0c;但是级联组件必须选到子节点&#xff0c;不能只选省&#xff0c;满足不了页面的需求 2、环境准备 1、react18 2、antd 4 3、功能实现 …

C++泛型编程:类模板(下)

类模板与继承&#xff1a; 需要指定模板参数的类型 template <class T> class Base { public:T m; }; class Son :public Base<int> { }; template <typename T1,typename T2> class Son2 :public Base<T2> { public:Son2(){cout << "T1的…

IntelliScraper 更新 --可自定义最大输出和相似度 支持Html的内容相似度匹配

场景 之前我们在使用IntelliScraper 初代版本的时候&#xff0c;不少人和我反馈一个问题&#xff0c;那就是最大输出结果只有50个&#xff0c;而且还带有html内容&#xff0c;不支持自动化&#xff0c;我声明一下&#xff0c;自动化目前不会支持&#xff0c;以后也不会支持&am…