#include <iostream>
#include <string>
#include <string.h>
#include <cstring>
#include <iomanip>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/signalfd.h>
std::string setSendData(uint8_t c); //
int set_sig_task(int sig_no); // 设置sig task
int setup_signal_fd(int sig_no); // 设置信号描述符
const int MAX_EVENTS = 10;
const int PORT = 50002;
void set_nonblocking(int fd)
{
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
int main()
{
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[2048] = {0};
// 创建套接字
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置端口复用
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// 绑定套接字到端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听端口
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
std::cout << "Server is listening on port " << PORT << std::endl;
// 创建 epoll 实例
int epoll_fd = epoll_create1(0);
if (epoll_fd == -1)
{
perror("epoll_create1");
exit(EXIT_FAILURE);
}
// 将 server_fd 添加到 epoll 事件列表中
struct epoll_event ev, events[MAX_EVENTS];
ev.events = EPOLLIN;
ev.data.fd = server_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) == -1)
{
perror("epoll_ctl: server_fd");
exit(EXIT_FAILURE);
}
// 设置标准输入为非阻塞并添加到 epoll 事件列表中
set_nonblocking(STDIN_FILENO);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = STDIN_FILENO;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1)
{
perror("epoll_ctl: STDIN_FILENO");
exit(EXIT_FAILURE);
}
int sig_fd = set_sig_task(SIGINT); //设置sig task
if(sig_fd != -1)
{
ev.events = EPOLLIN;
ev.data.fd = sig_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sig_fd, &ev) == -1)
{
perror("epoll_ctl: server_fd");
exit(EXIT_FAILURE);
}
}
bool exit_while = false;
while (!exit_while)
{
int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
if (nfds == -1)
{
perror("epoll_wait");
exit(EXIT_FAILURE);
}
for (int n = 0; n < nfds; ++n)
{
if (events[n].data.fd == server_fd)
{
// 处理新的连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
set_nonblocking(new_socket);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = new_socket;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_socket, &ev) == -1)
{
perror("epoll_ctl: new_socket");
exit(EXIT_FAILURE);
}
std::cout << "Accepted connection from client" << std::endl;
}
else if(events[n].data.fd == sig_fd)
{
signalfd_siginfo fdsi;
ssize_t s = read(sig_fd, &fdsi, sizeof(signalfd_siginfo));
if (s == sizeof(signalfd_siginfo))
{
if (fdsi.ssi_signo == SIGINT)
{
printf("Received SIGINT, exiting...\n");
exit_while = true;
}
}
}
else if (events[n].data.fd == STDIN_FILENO)
{
// 处理标准输入(按键操作)
char c[64];
int recv_len = read(STDIN_FILENO, c, 64);
if (recv_len == -1 && errno != EAGAIN)
{
perror("read");
exit(EXIT_FAILURE);
}
if (new_socket != -1)
{
uint8_t input_c = 0;
if (c[0] >= '0' && c[0] <= '9')
{
std::cout << "key pressed char " << c[0] << std::endl;
input_c = c[0] - 48;
std::string send_str = testVecEventSend(input_c); // vec event 发送
if (send_str != std::string())
{
send(new_socket, send_str.c_str(), send_str.length(), 0);
std::cout << "tcp send length:" << send_str.length();
std::cout << " data(0x):" << std::endl;
for (uint8_t send_str : send_str)
std::cout << std::hex << std::setfill('0') << std::setw(2) << (uint)send_str << " ";
std::cout << std::dec << std::endl;
}
}
else
std::cout << "Invalid key pressed char " << c[0] << " " << (uint)c[0] << std::endl;
}
}
else
{
// 处理客户端发送的数据
int client_fd = events[n].data.fd;
int valread = read(client_fd, buffer, 2048);
if (valread == -1 && errno != EAGAIN)
{
perror("read");
close(client_fd);
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
}
else if (valread == 0)
{
// 客户端关闭连接
std::cout << "Client disconnected" << std::endl;
close(client_fd);
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
}
else
{
std::cout << "tcp recv length:" << valread;
std::cout << " data(0x):" << std::endl;
for (int i = 0; i < valread; ++i)
std::cout << std::hex << std::setfill('0') << std::setw(2) << (uint)(uint8_t)buffer[i] << " ";
std::cout << std::dec << std::endl
<< std::endl;
}
}
}
}
close(sig_fd);
close(server_fd);
close(epoll_fd);
std::cout << "Server end" << std::endl;
return 0;
}
//
std::string setSendData(uint8_t c)
{
std::string str_data;
//str_data自己定义
return str_data;
}
// 设置sig task
int set_sig_task(int sig_no)
{
int sig_fd = setup_signal_fd(sig_no); // 设置信号文件描述符
if (sig_fd == -1)
{
std::cout << "[ERROR][set_sig_task]setup_signal_fd error" << std::endl;
return -1;
}
return sig_fd;
}
// 设置信号描述符
int setup_signal_fd(int sig_no)
{
sigset_t mask;
int sig_fd = -1;
// 初始化信号集变量
sigemptyset(&mask);
sigaddset(&mask, sig_no);
// 阻塞 SIGINT 信号
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
{
std::cout << "[ERROR][setup_signal_fd]sigprocmask error" << std::endl;
return -1;
}
// 创建信号文件描述符
sig_fd = signalfd(-1, &mask, 0);
if (sig_fd == -1)
{
std::cout << "[ERROR][setup_signal_fd]signalfd error" << std::endl;
return -1;
}
return sig_fd;
}