//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)
转载于:https://blog.51cto.com/10541556/1795902