一个TCP服务端

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值