epoll tcp server 演示收发消息
  MJlmRDrYd0Ow 2023年11月02日 38 0


#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>

struct tcp_server_config {
const char *ip = "127.0.0.1";
int port = 12345;
int backlog = 1024;
int epoll_timeout = 5000; // 5s
};
enum class tcp_server_error_code {
SOCKET_NO_ERROR,
SOCKET_CREATE_FAILED,
SOCKET_BIND_FAILED
};
class epoll_tcp_server {
#define SAFE_DELETE_ARRAY(ptr) do { if (nullptr != ptr) { delete [] ptr; ptr = nullptr; } } while (0)
public:
epoll_tcp_server() = default;
epoll_tcp_server(const epoll_tcp_server &) = delete;
epoll_tcp_server & operator = (const epoll_tcp_server &) = delete;
virtual ~epoll_tcp_server() {
close(sock_fd_);
sock_fd_ = -1;
close(epfd_);
epfd_ = -1;
SAFE_DELETE_ARRAY(events_);
}
bool init() {
tcp_server_error_code ret_code = create_sock_fd();
if (tcp_server_error_code::SOCKET_NO_ERROR != ret_code) {
print_error_code(ret_code);
return false;
}
if (false == create_epfd()) {
return false;
}
if (false == epoll_add(sock_fd_)) {
return false;
}
try {
events_ = new struct epoll_event[fd_capacity_];
memset(events_, 0x00, fd_capacity_ * sizeof(struct epoll_event));
}
catch (...) {
std::cerr << "new struct epoll_event failed." << std::endl;
return false;
}
init_succ = true;
return true;
}
inline void set_config(const tcp_server_config &config) {
config_ = config;
}
inline void set_fd_capacity(int cap) {
fd_capacity_ = cap;
}
inline void set_buffer_size(int size) {
buff_size_ = size;
}
virtual void tcp_message_process(const char *message, size_t size, std::string &output) {
output.assign(message, size);
}
void run() {
if (false == init_succ) {
std::cerr << "epoll tcp server init failed." << std::endl;
return;
}
while (true) {
int event_num = epoll_wait(epfd_, events_, fd_capacity_, config_.epoll_timeout);
if (event_num < 0) {
std::cerr << "epoll_wait failed." << std::endl;
break;
}
if (0 == event_num) {
std::cerr << "epoll_wait timeout." << std::endl;
continue;
}
run_core(event_num);
}
}
public:
inline static void set_non_blocking(int fd) {
int old_mode = fcntl(fd, F_GETFL);
int new_mode = old_mode | O_NONBLOCK;
fcntl(fd, F_SETFL, new_mode);
}
private:
tcp_server_error_code create_sock_fd() {
sock_fd_ = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd_ < 0) {
return tcp_server_error_code::SOCKET_CREATE_FAILED;
}
struct sockaddr_in saddr = {0};
saddr.sin_family = AF_INET;
saddr.sin_port = htons(config_.port);
saddr.sin_addr.s_addr = inet_addr(config_.ip);
if (bind(sock_fd_, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
return tcp_server_error_code::SOCKET_BIND_FAILED;
}
listen(sock_fd_, config_.backlog);
return tcp_server_error_code::SOCKET_NO_ERROR;
}
inline bool create_epfd() {
epfd_ = epoll_create(fd_capacity_);
return epfd_ >= 0;
}
void print_error_code(tcp_server_error_code ret_code) {
switch (ret_code) {
case tcp_server_error_code::SOCKET_CREATE_FAILED:
std::cerr << "epoll server socket create failed." << std::endl;
break;
case tcp_server_error_code::SOCKET_BIND_FAILED:
std::cerr << "epoll server socket bind failed." << std::endl;
break;
}
}
inline bool epoll_add(int fd) {
struct epoll_event ev = {0};
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = fd;
if (epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ev) < 0) {
std::cerr << "epoll_ctl add failed." << std::endl;
return false;
}
return true;
}
inline bool epoll_del(int fd) {
if (epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, nullptr) < 0) {
std::cerr << "epoll_ctl del failed." << std::endl;
return false;
}
return true;
}
void accept_new_client() {
struct sockaddr_in client_addr = { 0 };
int len = sizeof(client_addr);
int conn_fd = accept(sock_fd_, (struct sockaddr *)&client_addr, (socklen_t *)&len);
if (conn_fd < 0) {
return;
}
std::cout << "connection fd = " << conn_fd << std::endl;
epoll_add(conn_fd);
}
void process_client_message(int fd) {
char *buf = new (std::nothrow)char [buff_size_];
if (nullptr == buf) {
std::cerr << "new tcp buffer failed." << std::endl;
return;
}
memset(buf, 0x00, buff_size_);
size_t len = recv(fd, buf, buff_size_, 0);
if (0 == len) {
epoll_del(fd);
close(fd);
std::cerr << "client fd = " << fd << " over." << std::endl;
return;
}
std::cerr << "server recv buf = " << buf << std::endl;
std::string output;
tcp_message_process(buf, len, output);
SAFE_DELETE_ARRAY(buf);
send(fd, output.c_str(), output.size(), 0);
}
void run_core(int event_num) {
int fd = -1;
for (int i = 0;i < event_num;i++) {
fd = events_[i].data.fd;
if (fd < 0) {
continue;
}
if (!(events_[i].events & EPOLLIN)) {
continue;
}
set_non_blocking(fd);
if (fd == sock_fd_) {
accept_new_client();
}
else {
process_client_message(fd);
}
}
}
private:
int fd_capacity_ = 1024;
int buff_size_ = 1024;
private:
bool init_succ = false;
tcp_server_config config_;
int sock_fd_ = -1;
int epfd_ = -1;
struct epoll_event *events_ = nullptr;
};
int main() {
epoll_tcp_server tcp_server;
if (false == tcp_server.init()) {
return -1;
}
tcp_server.run();

return 0;
}

 

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  rEZj93RghFYQ   2023年11月02日   32   0   0 i++leetcode-java
MJlmRDrYd0Ow
最新推荐 更多