#include #include #include #include #include #include #include #include #include "drv_tcp_server.h" // 包含您提供的头文件 #define MAX_TCP_LEN 1024 // 假设MAX_TCP_LEN定义为1024 #define MAX_EVENTS 10 // epoll等待的最大事件数 #define MAX_CLIENTS 10 // 最多客户端数 /***************************************************************************** * @brief 设置文件描述符为非阻塞模式 * @param[in] fd:文件描述符 * @return 0-成功 1-失败 *****************************************************************************/ static int setNonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror("fcntl F_GETFL failed"); return 1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl F_SETFL failed"); return 1; } return 0; } /***************************************************************************** * @brief 打开tcp驱动 * @param[in] p_tcp: * @return 0-成功 1-失败 *****************************************************************************/ int drvTcpServerOpen(tcp_server_lib_t* p_tcp) { if (p_tcp == NULL) { return 1; } // 创建socket p_tcp->socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (p_tcp->socket_fd < 0) { perror("socket creation failed"); return 1; } // 设置SO_REUSEADDR以快速重用端口 int opt = 1; if (setsockopt(p_tcp->socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { perror("setsockopt failed"); close(p_tcp->socket_fd); return 1; } // 设置IP和端口 struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(p_tcp->port); if (inet_pton(AF_INET, p_tcp->ip, &server_addr.sin_addr) <= 0) { perror("Invalid IP address"); close(p_tcp->socket_fd); return 1; } // 绑定socket到IP和端口 if (bind(p_tcp->socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("Bind failed"); close(p_tcp->socket_fd); return 1; } // 开始监听 if (listen(p_tcp->socket_fd, MAX_CLIENTS) < 0) { perror("Listen failed"); close(p_tcp->socket_fd); return 1; } // 设置非阻塞模式 if (setNonblocking(p_tcp->socket_fd) > 0) { close(p_tcp->socket_fd); return 1; } // 创建epoll实例 p_tcp->epoll_fd = epoll_create1(0); if (p_tcp->epoll_fd == -1) { perror("epoll_create1 failed"); close(p_tcp->socket_fd); return 1; } // 将监听socket添加到epoll实例中 struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = p_tcp->socket_fd; if (epoll_ctl(p_tcp->epoll_fd, EPOLL_CTL_ADD, p_tcp->socket_fd, &ev) == -1) { perror("epoll_ctl failed"); close(p_tcp->socket_fd); close(p_tcp->epoll_fd); return 1; } p_tcp->isListen = 1; p_tcp->status = 1; // 表示在线 printf("Server is listening on %s:%d\n", p_tcp->ip, p_tcp->port); return 0; } /***************************************************************************** * @brief 关闭tcp驱动 * @param[in] p_tcp: tcp驱动结构体指针 * @return 0-成功 1-失败 *****************************************************************************/ int drvTcpServerClose(tcp_server_lib_t* p_tcp) { if (p_tcp == NULL || p_tcp->socket_fd < 0) { return 1; } // 关闭所有已连接的客户端 for (int i = 0; i < p_tcp->nClient; i++) { if (p_tcp->clients[i].fd >= 0) { close(p_tcp->clients[i].fd); } } // 关闭服务器socket和epoll实例 close(p_tcp->socket_fd); close(p_tcp->epoll_fd); p_tcp->isListen = 0; p_tcp->status = 0; // 设置为离线 printf("Server closed\n"); return 0; } /***************************************************************************** * @brief tcp驱动发送 * @param[in] p_tcp: tcp驱动结构体指针 * @return 0-成功 1-失败 *****************************************************************************/ ssize_t drvTcpServerSend(tcp_server_lib_t* p_tcp) { if (p_tcp == NULL || p_tcp->send_len == 0) { return -1; } ssize_t total_sent = 0; for (int i = 0; i < p_tcp->nClient; i++) { if (p_tcp->clients[i].fd >= 0) { ssize_t sent = send(p_tcp->clients[i].fd, p_tcp->send_buf, p_tcp->send_len, 0); if (sent < 0 || sent != p_tcp->send_len) { perror("Send failed"); return -1; } total_sent += sent; } } return total_sent; } /***************************************************************************** * @brief tcp驱动接收 * @param[in] p_tcp: tcp驱动结构体指针 * @return 0-成功 1-失败 *****************************************************************************/ ssize_t drvTcpServerRecv(tcp_server_lib_t* p_tcp) { if (p_tcp == NULL) { return -1; } struct epoll_event events[MAX_EVENTS]; int nfds = epoll_wait(p_tcp->epoll_fd, events, MAX_EVENTS, p_tcp->timeout); if (nfds == -1) { perror("epoll_wait failed"); return -1; } ssize_t total_recv = 0; for (int i = 0; i < nfds; i++) { int fd = events[i].data.fd; if (fd == p_tcp->socket_fd) { // 有新的客户端连接 struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int client_fd = accept(p_tcp->socket_fd, (struct sockaddr*)&client_addr, &addr_len); if (client_fd == -1) { perror("accept failed"); continue; } // 设置新连接为非阻塞 if (setNonblocking(client_fd) > 0) { close(client_fd); continue; } // 添加新客户端到epoll监听 struct epoll_event ev; ev.events = EPOLLIN | EPOLLET; ev.data.fd = client_fd; if (epoll_ctl(p_tcp->epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1) { perror("epoll_ctl add client failed"); close(client_fd); continue; } // 添加到客户端列表中 if (p_tcp->nClient < MAX_CLIENTS) { p_tcp->clients[p_tcp->nClient].fd = client_fd; p_tcp->clients[p_tcp->nClient].client = client_addr; p_tcp->nClient++; printf("New client connected\n"); } else { printf("Max clients reached\n"); close(client_fd); } } else { // 接收客户端数据 ssize_t recv_len = recv(fd, p_tcp->recv_buf, MAX_TCP_LEN, 0); if (recv_len < 0) { if (errno != EWOULDBLOCK && errno != EAGAIN) { perror("Receive failed"); close(fd); epoll_ctl(p_tcp->epoll_fd, EPOLL_CTL_DEL, fd, NULL); } } else if (recv_len == 0) { // 客户端断开连接 close(fd); epoll_ctl(p_tcp->epoll_fd, EPOLL_CTL_DEL, fd, NULL); printf("Client disconnected\n"); } else { total_recv += recv_len; p_tcp->recv_len = recv_len; // 更新接收数据的长度 } } } return total_recv; }