simple udp server with libevent

256 篇文章 3 订阅
149 篇文章 2 订阅

1.socket_config.hpp

#ifndef SOCKET_CONFIG_HPP_
#define SOCKET_CONFIG_HPP_
#include <string>
using namespace std;
enum {
	TCP,
	UDP
};
class socket_config {
public:
	socket_config() {
		port_ = 8080;
		backlog_ = 1024;
		type_ = UDP;
		ip_ = "127.0.0.1";
	}
	virtual ~socket_config() = default;
public:
	int port_;
	int backlog_;
	unsigned char type_;
	string ip_;
};

#endif /* SOCKET_CONFIG_HPP_ */

2.sockect_utility.hpp

#ifndef SOCKET_UTILITY_HPP_
#define SOCKET_UTILITY_HPP_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include "socket_config.hpp"
class sockect_utility {
public:
	inline static sockect_utility &get_instance() {
		static sockect_utility obj;
		return obj;
	}
private:
	sockect_utility() = default;
	virtual ~sockect_utility() = default;
public:
	int bind_socket(const socket_config &config) {
		int sock_fd = init_socket(config.type_);
		if (-1 == sock_fd) {
			return -1;
		}
		struct sockaddr_in addr = {0};
		addr.sin_family = AF_INET;
		addr.sin_addr.s_addr = inet_addr(config.ip_.c_str());
		addr.sin_port = htons(config.port_);
		if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
			cerr << "socket bind failed on ip = " << config.ip_ << " port = " << config.port_ << endl;
			return -1;
		}
		if (TCP == config.type_) {
			if (listen(sock_fd, config.backlog_) < 0) {
				cerr << "socket listen failed on backlog = " << config.backlog_ << endl;
				return -1;
			}
		}
		int flag = 0;
		flag = fcntl(sock_fd, F_GETFL, 0);
		if (flag < 0) {
			cerr << "fcntl F_GETFL on socket = " << sock_fd << " failed...!" << endl;
			return -1;
		}
		if (fcntl(sock_fd, F_SETFL, flag | O_NONBLOCK) < 0) {
			cerr << "fcntl F_SETFL non block on socket = " << sock_fd << " failed...!" << endl;
			return -1;
		}
		return sock_fd;
	}
	bool close_socket(int &sock_fd) {
		if (sock_fd >= 0) {
			close(sock_fd);
			sock_fd = -1;
			return true;
		}
		return false;
	}
private:
	int init_socket(unsigned char type) {
		int sock_fd = -1;
		switch (type) {
		case UDP:
			sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
			break;
		case TCP:
			sock_fd = socket(AF_INET, SOCK_STREAM, 0);
			break;
		default:
			cerr << "unknown socket type...!" << endl;
			return -1;
		}
		if (sock_fd < 0) {
			cerr << "socket fd create failed...!" << endl;
			return -1;
		}
		int on = 1;
		if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) {
			cerr << "set socket to resue failed...!" << endl;
			return -1;
		}
		if (setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) {
			cerr << "set socket to keep alive failed...!" << endl;
			return -1;
		}
		return sock_fd;
	}
};


#endif /* SOCKET_UTILITY_HPP_ */

3.udp_thread.hpp

#ifndef UDP_THREAD_HPP_
#define UDP_THREAD_HPP_
#include "socket_utility.hpp"
#include <event.h>
#include <event2/listener.h>
class udp_thread {
public:
	udp_thread() {
		sock_fd_ = -1;
		base_ = nullptr;
		event_ = nullptr;
	}
	virtual ~udp_thread() {
		if (base_ != nullptr) {
			event_base_loopexit(base_, NULL);
			event_base_free(base_);
			base_ = nullptr;
		}
		if (event_ != nullptr) {
			event_free(event_);
			event_ = nullptr;
		}
	}
public:
	bool init(int fd) {
		if (fd < 0) {
			return false;
		}
		sock_fd_ = fd;
		base_ = event_base_new();
		if (nullptr == base_) {
			return false;
		}
		event_ = event_new(base_, sock_fd_, EV_READ | EV_PERSIST, read_udp_cb, this);
		if (nullptr == event_) {
			return false;
		}
		return 0 == event_add(event_, NULL);
	}
	void udp_dispatch_event() {
		if (base_ != nullptr) {
			event_base_dispatch(base_);
		}
	}
	virtual bool deal_udp_message(int fd) = 0;
public:
	static void read_udp_cb(int fd, short event, void *arg) {
		udp_thread *p = reinterpret_cast<udp_thread *>(arg);
		if (nullptr == p) {
			return;
		}
		p->deal_udp_message(fd);
	}
protected:
	int sock_fd_;
	event_base *base_;
	event *event_;
protected:
	const int buffer_size = 1024;
};

#endif /* UDP_THREAD_HPP_ */

4._thead_for_transaction.hpp

#ifndef UDP_THREAD_FOR_TRANSACTION_HPP_
#define UDP_THREAD_FOR_TRANSACTION_HPP_
#include "udp_thread.hpp"
class udp_thead_for_transaction : public udp_thread {
public:
	udp_thead_for_transaction() = default;
	virtual ~udp_thead_for_transaction() = default;
public:
	virtual bool deal_udp_message(int fd) {
		char buf[buffer_size] = "";
		socklen_t size = sizeof(struct sockaddr);
		struct sockaddr_in client_addr = {0};
		int len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &size);
		if (len < 0) {
			cerr << "server recv message error...!" << endl;
			return false;
		}
		if (0 == len) {
			cerr << "connection closed...!" << endl;
		}
		cout << "connection port = " << client_addr.sin_port << endl;
		cout << "connection ip = " << inet_ntoa(client_addr.sin_addr) << endl;
		cout << "server recv message len = " << len << endl;
		cout << "sever send back message now...!" << endl;
		sendto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, size);
		return true;
	}
};


#endif /* UDP_THREAD_FOR_TRANSACTION_HPP_ */

5.udp_server.hpp

#ifndef UDP_SERVER_HPP_
#define UDP_SERVER_HPP_
#include <vector>
#include <thread>
#include <memory>
#include "udp_thread_for_transaction.hpp"

class udp_server {
public:
	udp_server(const socket_config &config) : sock_fd_(-1), config_(config) {
	}
	virtual ~udp_server() {
		for (auto &it : threads_) {
			if (it.joinable()) {
				it.join();
			}
		}
		sockect_utility::get_instance().close_socket(sock_fd_);
	}
public:
	bool init(int network_size) {
		if (network_size <= 0 || network_size > network_capacity) {
			return false;
		}
		sock_fd_ = sockect_utility::get_instance().bind_socket(config_);
		if (sock_fd_ < 0) {
			return false;
		}
		threads_.resize(network_size);
		for (int i = 0;i < network_size;i++) {
			udp_threads_.emplace_back(unique_ptr<udp_thread>(new udp_thead_for_transaction));
			if (false == udp_threads_[i]->init(sock_fd_)) {
				cerr << "udp thread init failed...!" << endl;
				continue;
			}
			try {
				threads_[i] = thread(std::bind(&udp_server::start_udp_thread, this, i));
			}
			catch (...) {
				return false;
			}
		}
		return true;
	}
private:
	void start_udp_thread(int index) {
		udp_threads_[index]->udp_dispatch_event();
	}
private:
	socket_config config_;
	vector<unique_ptr<udp_thread> >udp_threads_;
	vector<thread>threads_;
private:
	int sock_fd_;
private:
	const int network_capacity = 128;
};

#endif /* UDP_SERVER_HPP_ */

6.main.cpp

#include "udp_server.hpp"
int main() {
	socket_config config;
	udp_server server(config);
	cout << server.init(thread::hardware_concurrency()) << endl;

	return 0;
}

7.udp_client.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <iostream>
using namespace std;
int main() {
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    char buf[] = "hello server I am client...!";
    for (int i = 0;i < 10;i++) {
        sendto(sockfd, &buf, strlen(buf), 0, (struct sockaddr*)&addr,sizeof(addr));
        socklen_t len = sizeof(addr);
        char tmp[1024] = "";
        recvfrom(sockfd, tmp, sizeof(tmp), 0,(struct sockaddr*)&addr,&len);
        if (tmp[0])
        {
            cout << "client recv = " << tmp << endl;
        }
    }
    close(sockfd);
}

7.make.sh

g++ -std=c++11 -g -o udpserver main.cpp socket_config.hpp socket_utility.hpp udp_thread.hpp udp_thread_for_transaction.hpp udp_server.hpp -levent -pthread
g++ -std=c++11 -g -o udpclient udp_client.cpp

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值