使用epoll和本地socket的例子
时间: 2023-09-21 08:06:01 浏览: 225
### 回答1:
这是一个使用epoll和本地socket的例子:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define MAX_EVENTS 10
#define MAX_BUF_SIZE 1024
int main(int argc, char *argv[]) {
int server_fd, client_fd, epoll_fd, n, i;
struct epoll_event ev, events[MAX_EVENTS];
struct sockaddr_in server_addr, client_addr;
char buf[MAX_BUF_SIZE];
// 创建服务器socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// 绑定服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8888);
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
// 监听连接请求
if (listen(server_fd, SOMAXCONN) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 创建epoll实例
if ((epoll_fd = epoll_create1(0)) < 0) {
perror("epoll_create1");
exit(EXIT_FAILURE);
}
// 将服务器socket加入epoll事件
ev.events = EPOLLIN;
ev.data.fd = server_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) < 0) {
perror("epoll_ctl: server_fd");
exit(EXIT_FAILURE);
}
while (1) {
n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
for (i = 0; i < n; i++) {
if (events[i].data.fd == server_fd) { // 有新连接请求
socklen_t client_len = sizeof(client_addr);
if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 将客户端socket加入epoll事件
ev.events = EPOLLIN;
ev.data.fd = client_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) < 0) {
perror("epoll_ctl: client_fd");
exit(EXIT_FAILURE);
}
} else { // 有客户端数据可读
memset(buf, 0, MAX_BUF_SIZE);
if (read(events[i].data.fd, buf, MAX_BUF_SIZE) < 0) {
perror("read");
exit(EXIT_FAILURE);
}
printf("Received message: %s", buf);
// 回复客户端
if (write(events[i].data.fd, buf, strlen(buf)) < 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
}
}
return 0;
}
```
这个例子创建了一个本地socket服务器,监听端口号为8888,使用epoll来处理多个客户端连接。服务器首先创建一个socket并绑定到本地地址,然后监听连接请求。
### 回答2:
epoll是Linux操作系统中用于I/O事件驱动的机制,它可以同时监测多个文件描述符上的事件。本地socket是一种在同一台机器上进行进程间通讯的方法。下面是一个使用epoll和本地socket的例子:
我们假设有一个服务器程序和多个客户端程序运行在同一台机器上。服务器使用本地socket监听客户端的连接请求,客户端通过本地socket与服务器进行通讯。
服务器端代码如下所示:
```c
#include <stdio.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 10
#define BUF_SIZE 1024
int main() {
int server_sock, client_sock, epoll_fd, event_count, i;
struct sockaddr_in server_addr, client_addr;
struct epoll_event event, events[MAX_EVENTS];
socklen_t addr_size = sizeof(client_addr);
char buf[BUF_SIZE];
// 创建本地socket
server_sock = socket(AF_INET, SOCK_STREAM, 0);
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12345);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定本地socket到服务器地址
bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
// 监听客户端连接请求
listen(server_sock, 5);
// 创建epoll文件描述符
epoll_fd = epoll_create1(0);
// 将服务器端socket添加到epoll监听中
event.events = EPOLLIN;
event.data.fd = server_sock;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_sock, &event);
while (1) {
// 启动epoll等待事件
event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
// 处理所有触发的事件
for (i = 0; i < event_count; i++) {
// 处理新的客户端连接请求
if (events[i].data.fd == server_sock) {
client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &addr_size);
// 将新的客户端添加到epoll监听中
event.events = EPOLLIN;
event.data.fd = client_sock;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &event);
printf("Client connected: %s\n", inet_ntoa(client_addr.sin_addr));
}
// 处理客户端发来的消息
else {
memset(buf, 0, sizeof(buf));
recv(events[i].data.fd, buf, BUF_SIZE, 0);
printf("Receive message from client: %s\n", buf);
}
}
}
// 关闭所有socket和epoll文件描述符
close(server_sock);
close(epoll_fd);
return 0;
}
```
客户端代码如下所示:
```c
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUF_SIZE 1024
int main() {
int client_sock;
struct sockaddr_in server_addr;
char buf[BUF_SIZE] = "Hello, Server!";
// 创建本地socket
client_sock = socket(AF_INET, SOCK_STREAM, 0);
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12345);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 连接到服务器
connect(client_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
// 发送消息给服务器
send(client_sock, buf, sizeof(buf), 0);
// 关闭socket
close(client_sock);
return 0;
}
```
以上是一个简单的使用epoll和本地socket的例子。服务器程序使用epoll来监听客户端连接请求和处理客户端发来的消息,而客户端程序则使用本地socket连接到服务器并发送消息。
### 回答3:
epoll是一种用于事件通知的高效机制,而本地socket是一种用于进程间通信的方式。它们可以结合使用来实现高效的通信。
一个使用epoll和本地socket的例子是多进程TCP服务器。首先,创建一个本地socket,并将其绑定到一个指定的地址和端口上。然后,创建多个子进程,每个子进程负责处理一个客户端连接。在子进程中,使用epoll监听本地socket和客户端连接上的事件。
当有客户端连接请求到达时,主进程接受该连接请求,并将客户端的socket文件描述符传递给一个子进程。子进程将该socket文件描述符添加到epoll的监听列表中。然后,子进程通过epoll的等待事件函数进行监听,并处理已就绪的事件。
当有数据到达时,子进程会收到数据可读事件。子进程通过socket读取数据,并进行相应的处理。当处理完数据后,可以通过socket写回数据给客户端。
通过使用epoll和本地socket,多个客户端连接可以同时被处理,而不需要为每个客户端连接创建一个线程。这种方式避免了线程切换的开销,并提高了服务器的并发性能。
总结来说,使用epoll和本地socket的例子是实现多进程TCP服务器。通过在多个子进程中使用epoll监听本地socket和客户端连接上的事件,可以实现高效的并发通信。
阅读全文