linux c socket select 等待 accept 代码
时间: 2023-06-19 18:04:26 浏览: 227
以下是一个使用 `select` 函数等待 `accept` 的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#define LISTEN_BACKLOG 50
#define MAX_EVENTS 10
int main(int argc, char *argv[]) {
int listen_fd, conn_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len;
fd_set read_fds, write_fds, except_fds;
int max_fd, ret;
// 创建监听套接字
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket error");
exit(EXIT_FAILURE);
}
// 设置地址复用选项
int optval = 1;
if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
perror("setsockopt error");
exit(EXIT_FAILURE);
}
// 绑定地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind error");
exit(EXIT_FAILURE);
}
// 监听
if (listen(listen_fd, LISTEN_BACKLOG) < 0) {
perror("listen error");
exit(EXIT_FAILURE);
}
// 初始化 fd_set
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
FD_SET(listen_fd, &read_fds);
max_fd = listen_fd;
while (1) {
// 使用 select 等待读事件
ret = select(max_fd + 1, &read_fds, &write_fds, &except_fds, NULL);
if (ret < 0) {
perror("select error");
exit(EXIT_FAILURE);
}
// 处理读事件
if (FD_ISSET(listen_fd, &read_fds)) {
client_addr_len = sizeof(client_addr);
conn_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_addr_len);
if (conn_fd < 0) {
perror("accept error");
continue;
}
// 将新连接的套接字加入 fd_set
FD_SET(conn_fd, &read_fds);
if (conn_fd > max_fd) {
max_fd = conn_fd;
}
printf("new connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
// 处理其它读事件
for (int fd = listen_fd + 1; fd <= max_fd; fd++) {
if (FD_ISSET(fd, &read_fds)) {
// TODO: 处理读事件
}
}
// 清空 fd_set
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
FD_SET(listen_fd, &read_fds);
for (int fd = listen_fd + 1; fd <= max_fd; fd++) {
if (FD_ISSET(fd, &read_fds) || FD_ISSET(fd, &write_fds) || FD_ISSET(fd, &except_fds)) {
FD_SET(fd, &read_fds);
}
}
}
exit(EXIT_SUCCESS);
}
```
代码中使用 `select` 函数等待监听套接字的读事件,一旦监听套接字上有新的连接请求,就调用 `accept` 函数接受连接,并将新连接的套接字加入 `fd_set` 中,并更新 `max_fd`。然后在 `for` 循环中遍历其它套接字,处理读事件。最后清空 `fd_set`,重新添加需要监听的套接字。
阅读全文