//data_pool.h #include<iostream> #include<vector> #include <semaphore.h> #include"comm.h" using namespace std; #define _CAP_ 256 class data_pool { public: data_pool(int size=_CAP_); void data_put(string& _in); void data_get(string& _out); ~data_pool(); private: vector<string> pool; int get_index; int put_index; int capacity; sem_t put_sem; sem_t get_sem; }; //data_pool.cpp #include"data_pool.h" data_pool::data_pool(int size) :get_index(0) ,put_index(0) ,capacity(size) ,pool(size) { sem_init(&put_sem, 0, capacity); sem_init(&get_sem, 0, 0); } void data_pool::data_put(string& _in) { sem_wait(&put_sem);//p pool[put_index++]=_in; put_index%=capacity; sem_post(&get_sem);//v } void data_pool::data_get(string& _out) { sem_wait(&get_sem);//p pool[get_index++]=_out; get_index%=capacity; sem_post(&put_sem);//v } data_pool::~data_pool() { sem_destroy(&put_sem); sem_destroy(&get_sem); } //udp_server.h #include<iostream> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<stdio.h> #include<string.h> #include<string> #include<stdlib.h> #include<map> #include"comm.h" #include"data_pool.h" #define _DEFAULT_IP_ "127.0.0.1" #define _DEFAULT_PORT_ 8080 class udp_server { public: udp_server(string _ip=_DEFAULT_IP_,short _port=_DEFAULT_PORT_); void init(); void add_user(string& ip,struct sockaddr_in& client); int send_data(struct sockaddr_in& client,socklen_t size,string& msg); int recv_data(); int broadcast(); ~udp_server(); private: string ip; short port; int sock; data_pool pool; map<string,struct sockaddr_in> user_online; }; //udp_client.cpp #include"udp_server.h" udp_server::udp_server(string _ip,short _port) :ip(_ip) ,port(_port) ,sock(-1) {} void udp_server::init() { sock=socket(AF_INET,SOCK_DGRAM,0); if(sock<0) { print_log(strerror(errno),__FUNCTION__,__LINE__); exit(1); } struct sockaddr_in local; local.sin_family=AF_INET; local.sin_port=htons(port); if(ip=="any") local.sin_addr.s_addr=htonl(INADDR_ANY); else local.sin_addr.s_addr=inet_addr(ip.c_str()); if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0) { print_log(strerror(errno),__FUNCTION__,__LINE__); exit(2); } } void udp_server::add_user(string& ip,struct sockaddr_in& client) { map<string,struct sockaddr_in>::iterator iter=user_online.find(ip); if(iter==user_online.end()) { user_online.insert(pair<string,struct sockaddr_in>(ip,client)); } else return; } int udp_server::send_data(struct sockaddr_in& client,socklen_t size,string& msg) { ssize_t _s=sendto(sock,msg.c_str(),msg.size(),0,(struct sockaddr*)&client,size); if(_s<0) { print_log(strerror(errno),__FUNCTION__,__LINE__); } cout<<"send"<<endl; return _s; } int udp_server::recv_data() { struct sockaddr_in remote; socklen_t len=sizeof(remote); char buf[_SIZE_]; ssize_t _s=recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&remote,&len); if(_s>0) { buf[_s]=‘\0‘; cout<<"client: "<<buf<<endl; string out=buf; pool.data_put(out); string key_ip=inet_ntoa(remote.sin_addr); add_user(key_ip,remote); } else if(_s==0) { print_log("client is close",__FUNCTION__,__LINE__); } else { print_log(strerror(errno),__FUNCTION__,__LINE__); } return _s; } int udp_server::broadcast() { string msg; pool.data_get(msg); map<string,struct sockaddr_in>::iterator iter=user_online.begin(); for(;iter!=user_online.end();++iter) { send_data(iter->second,sizeof(iter->second),msg); } return 0; } udp_server::~udp_server() { if(sock>0) { close(sock); } } //Makefile ROOT_PATH=$(shell pwd) SERVER=$(ROOT_PATH)/server CLIENT=$(ROOT_PATH)/client COMM=$(ROOT_PATH)/comm DATA_POOL=$(ROOT_PATH)/data_pool SERVER_BIN=udp_server CLIENT_BIN=udp_client INCLUDE=-I$(COMM) INCLUDE+=-I$(DATA_POOL) CC=g++ FLAGS= LDFLAGS=-lpthread#-static SER_SRC=$(shell ls -r $(SERVER) | grep -E ‘*.cpp‘) SER_SRC+=$(shell ls -r $(COMM) | grep -E ‘*.cpp‘) SER_SRC+=$(shell ls -r $(DATA_POOL) | grep -E ‘*.cpp‘) SER_OBJ=$(SER_SRC:.cpp=.o) CLI_SRC=$(shell ls -r $(CLIENT) | grep -E ‘*.cpp‘) CLI_SRC+=$(shell ls -r $(COMM) | grep -E ‘*.cpp‘) CLI_OBJ=$(CLI_SRC:.cpp=.o) .PHONY:all all:$(SERVER_BIN) $(CLIENT_BIN) $(SERVER_BIN):$(SER_OBJ) $(CC) -o $@ $^ $(LDFLAGS) $(CLIENT_BIN):$(CLI_OBJ) $(CC) -o $@ $^ $(LDFLAGS) %.o:$(COMM)/%.cpp $(CC) -c $< $(INCLUDE) %.o:$(DATA_POOL)/%.cpp $(CC) -c $< $(INCLUDE) %.o:$(SERVER)/%.cpp $(CC) -c $< $(INCLUDE) %.o:$(CLIENT)/%.cpp $(CC) -c $< $(INCLUDE) .PHONY:clean clean: rm -f *.o $(SERVER_BIN) $(CLIENT_BIN)
本文出自 “小止” 博客,请务必保留此出处http://10541556.blog.51cto.com/10531556/1795902
原文:http://10541556.blog.51cto.com/10531556/1795902