ConstStar
发布于 2024-11-29 / 10 阅读 / 0 评论 / 0 点赞

利用select实现模拟事件信号量并同时接收网络消息

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <thread>

int pipe_fd[2];

enum MOCK_EVENT_TYPE {
    MOCK_EVENT_TYPE_TEST1,
    MOCK_EVENT_TYPE_TEST2
};

bool InitMockEvent() {
    // 创建管道
    if (pipe(pipe_fd) == -1) {
        perror("pipe");
        return false;
    }
    return true;
}

// 模拟post
void PostMockEvent(MOCK_EVENT_TYPE event_type) {
    write(pipe_fd[1], &event_type, sizeof(event_type));
}


void thread1() {
    int client = 0;
    struct sockaddr_in server_addr;

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = htonl(0xc0a8029b);    // 192.168.2.155

    while(1) {
        do {
            printf("start");

            client = socket(AF_INET, SOCK_STREAM,0);
            if(client < 0) {
                perror("socket");
                break;
            }

            if(connect(client, (sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
                perror("connect");
                break;
            }

            printf("connect succ\r\n");
            int max_fd = (pipe_fd[0] > client) ? pipe_fd[0] : client;
            while (1) {
                fd_set readfds;
                FD_ZERO(&readfds);
                FD_SET(pipe_fd[0], &readfds); 
                FD_SET(client, &readfds); 

                // 模拟pend
                int result = select(max_fd + 1, &readfds, NULL, NULL, NULL);
                if (result < 0) {
                    perror("select");
                    break;
                }

                if (FD_ISSET(client, &readfds)) {
                    char buffer[1024];
                    ssize_t len = read(client, buffer, sizeof(buffer) - 1);
                    if (len > 0) {
                        buffer[len] = '\0';
                        printf("收到来自网络的消息:%s\r\n", buffer);
                    } else {
                        printf("网络消息接受失败:%d\r\n", len);
                    }
                }

                if (FD_ISSET(pipe_fd[0], &readfds)) {
                    MOCK_EVENT_TYPE event_type;
                    ssize_t len = read(pipe_fd[0], &event_type, sizeof(event_type));
                    if (len == sizeof(event_type)) {
                        if(event_type == MOCK_EVENT_TYPE_TEST1) {
                            printf("管道消息模拟触发MOCK_EVENT_TYPE_TEST1事件\r\n");
                        } else if(event_type == MOCK_EVENT_TYPE_TEST2) {
                            printf("管道消息模拟触发MOCK_EVENT_TYPE_TEST2事件\r\n");
                        } else {
                            printf("错误的消息类型\r\n");
                        }
                    } else {
                        printf("管道消息长度错误%d\r\n", len);
                        break;
                    }
                }
            }
        } while(0);

        if(client > 0)
            close(client);

        sleep(2);
    }
}

void thread2() {
    while(1) {
        PostMockEvent(MOCK_EVENT_TYPE_TEST1);
        sleep(2);
        PostMockEvent(MOCK_EVENT_TYPE_TEST2);
        sleep(3);
    }
}

int main() {
    
    if(!InitMockEvent()) {
        perror("InitMockEvent");
        exit(-1);
    }

    std::thread th1(thread1);
    std::thread th2(thread2);

    th1.detach();
    th2.join();
    return 0;
}

评论