首页 > 其他分享 >simple udp server with libevent

simple udp server with libevent

时间:2022-12-01 17:09:48浏览次数:43  
标签:udp return simple sock int fd libevent include


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

 

标签:udp,return,simple,sock,int,fd,libevent,include
From: https://blog.51cto.com/u_15899033/5902955

相关文章