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