DragonOS/user/apps/c_unitest/test_epoll_socket.c

222 lines
6.9 KiB
C

#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define SERVER_IP "111.111.11.1"
#define CLIENT_IP "111.111.11.2"
#define PORT 8888
#define MAX_EVENTS 10
#define BUFFER_SIZE 1024
// 函数声明
void server_process();
void client_process();
int main() {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// 子进程作为客户端
// 等待一秒,确保服务器已启动
sleep(1);
client_process();
} else {
// 父进程作为服务器
server_process();
}
return 0;
}
// 服务器进程逻辑
void server_process() {
printf("[Server] Starting server process...\n");
int listen_sock, conn_sock, epoll_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
struct epoll_event ev, events[MAX_EVENTS];
char buffer[BUFFER_SIZE];
int data_processed = 0; // 添加标志位,标记是否已处理过数据
if ((listen_sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0) {
perror("[Server] socket creation failed");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
perror("[Server] inet_pton failed");
exit(EXIT_FAILURE);
}
if (bind(listen_sock,
(struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
perror("[Server] bind failed");
exit(EXIT_FAILURE);
}
if (listen(listen_sock, 1) < 0) {
perror("[Server] listen failed");
exit(EXIT_FAILURE);
}
printf("[Server] Listening on %s:%d\n", SERVER_IP, PORT);
if ((epoll_fd = epoll_create1(0)) < 0) {
perror("[Server] epoll_create1 failed");
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &ev) < 0) {
perror("[Server] epoll_ctl: listen_sock failed");
exit(EXIT_FAILURE);
}
printf("Adding listening socket %d to epoll\n", listen_sock);
while (!data_processed) {
int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
if (nfds < 0) {
perror("[Server] epoll_wait failed");
exit(EXIT_FAILURE);
}
for (int n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
printf("trying to accept new connection...\n");
while (1) {
conn_sock = accept(listen_sock,
(struct sockaddr *)&client_addr,
&client_len);
if (conn_sock < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf("All incoming connections have been "
"processed.\n");
break;
} else {
perror("accept error");
exit(EXIT_FAILURE);
break;
}
}
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_sock, &ev) <
0) {
perror("[Server] epoll_ctl: conn_sock failed");
exit(EXIT_FAILURE);
}
printf("[Server] Accepted connection from %s:%d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
}
} else {
printf("[Server] handling client data...\n");
int client_fd = events[n].data.fd;
int nread = read(client_fd, buffer, BUFFER_SIZE);
if (nread == -1) {
if (errno != EAGAIN) {
perror("[Server] read error");
close(client_fd);
}
} else if (nread == 0) {
printf("[Server] Client disconnected.\n");
close(client_fd);
} else {
buffer[nread] = '\0';
printf("[Server] Received from client: %s\n", buffer);
write(client_fd, buffer, nread);
printf("[Server] Echoed data back to client. Server will "
"now exit.\n");
data_processed = 1; // 设置退出标志
sleep(3);
close(client_fd);
break;
}
}
}
}
printf("[Server] Server process completed.\n");
close(listen_sock);
close(epoll_fd);
}
// 客户端进程逻辑
void client_process() {
printf("[Client] Starting client process...\n");
int sock = 0;
struct sockaddr_in client_bind_addr, server_addr;
char buffer[BUFFER_SIZE] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("[Client] socket creation failed");
exit(EXIT_FAILURE);
}
memset(&client_bind_addr, 0, sizeof(client_bind_addr));
client_bind_addr.sin_family = AF_INET;
client_bind_addr.sin_port = htons(7777);
if (inet_pton(AF_INET, CLIENT_IP, &client_bind_addr.sin_addr) <= 0) {
perror("[Client] inet_pton for bind failed");
exit(EXIT_FAILURE);
}
if (bind(sock,
(struct sockaddr *)&client_bind_addr,
sizeof(client_bind_addr)) < 0) {
perror("[Client] bind failed");
exit(EXIT_FAILURE);
}
printf("[Client] Bound to IP %s\n", CLIENT_IP);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
perror("[Client] inet_pton for connect failed");
exit(EXIT_FAILURE);
}
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) <
0) {
perror("[Client] connect failed");
exit(EXIT_FAILURE);
}
printf("[Client] Connected to server %s:%d\n", SERVER_IP, PORT);
const char *message = "Hello from client";
write(sock, message, strlen(message));
printf("[Client] Sent: %s\n", message);
sleep(1);
int valread = read(sock, buffer, BUFFER_SIZE);
if (valread > 0) {
buffer[valread] = '\0';
printf("[Client] Received: %s\n", buffer);
}
printf("[Client] Client process completed.\n");
close(sock);
}