epoll实现简单聊天程序
立即下载
资源介绍:
epoll实现简单聊天程序, 终端输入接收cli端数据,c 和c++ 实现ser c实现cli,c++方式支持多个客户端
#include
#include
#include
#include
#include
#include
#include
#include
#define SOCKET_PATH "/tmp/chat.sock"
#define BUFFER_SIZE 1024
int main() {
int server_socket, client_socket;
struct sockaddr_un server_addr, client_addr;
socklen_t client_len;
int cli_fd = 0;
// 创建 Unix 域套接字
server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 清除旧的 socket 文件
unlink(SOCKET_PATH);
// 准备地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);
// 绑定套接字
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
// 开始监听
if (listen(server_socket, 1) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受客户端连接
/*client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
// 设置套接字为非阻塞模式
int flags = fcntl(client_socket, F_GETFL, 0);
fcntl(client_socket, F_SETFL, flags | O_NONBLOCK);
*/
char buffer[BUFFER_SIZE];
struct epoll_event events[3];
int epoll_fd = epoll_create1(0);
if (epoll_fd == -1) {
perror("epoll_create1");
exit(EXIT_FAILURE);
}
// 添加标准输入和客户端套接字到 epoll
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = STDIN_FILENO;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) {
perror("epoll_ctl (stdin)");
exit(EXIT_FAILURE);
}
event.events = EPOLLIN | EPOLLET; // 边缘触发模式
event.data.fd = server_socket;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket, &event) == -1) {
perror("epoll_ctl (client_socket)");
exit(EXIT_FAILURE);
}
while (1) {
int nready = epoll_wait(epoll_fd, events, 3, -1);
if (nready == -1) {
perror("epoll_wait");
break;
}
for (int i = 0; i < nready; ++i) {
if (events[i].data.fd == STDIN_FILENO) {
if (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {
if(cli_fd != 0)
write(cli_fd, buffer, strlen(buffer)); // 发送消息给客户端
}
}else if (events[i].data.fd == server_socket) {
printf("events[i].data.fd == server_socket accept\n");
client_len = sizeof(client_addr);
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1) {
perror("accept");
continue;
}
event.events = EPOLLIN | EPOLLET; // 边缘触发模式
event.data.fd = client_socket;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_socket, &event) == -1) {
perror("epoll_ctl (client_socket)");
continue;
}
cli_fd = client_socket;
}else/* if (events[i].data.fd == client_socket) */{
//printf("enter read, events[j].data.fd = 0x%x\n", events[i].data.fd);
ssize_t nread = read(events[i].data.fd, buffer, BUFFER_SIZE - 1);
if (nread > 0) {
buffer[nread] = '\0';
printf("Received: %s", buffer);
} else if (nread == 0) {
printf("Client disconnected.\n");
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
cli_fd = 0;
continue;
} else {
perror("Error reading from client");
break;
}
}
}
}
// 清理
close(client_socket);
close(server_socket);
close(epoll_fd);
unlink(SOCKET_PATH);
return 0;
}