目录
- 简单的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);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';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;}}}private:string _ip;uint16_t _port;int _sockid;func_t _func;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>const 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';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";}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;
};