使用C语言写一个select函数的监听socket 接受demo

时间: 2023-08-02 13:06:20 浏览: 58
下面是一个简单的使用select函数监听socket并接受数据的示例代码,其中使用了TCP协议: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define MAX_CLIENTS 10 #define BUFFER_SIZE 1024 int main(int argc, char *argv[]) { int server_fd, max_fd, activity, i, valread, new_socket, sd; struct sockaddr_in server_addr, client_addr; char buffer[BUFFER_SIZE]; fd_set readfds; // Create socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Set socket options int opt = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt failed"); exit(EXIT_FAILURE); } // Bind socket to address server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(8080); if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // Listen for incoming connections if (listen(server_fd, MAX_CLIENTS) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } // Accept incoming connections and add them to the set of file descriptors to monitor int addrlen = sizeof(client_addr); int client_sockets[MAX_CLIENTS] = {0}; for (i = 0; i < MAX_CLIENTS; ++i) { new_socket = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t*)&addrlen); if (new_socket < 0) { perror("accept failed"); exit(EXIT_FAILURE); } printf("New connection, socket fd is %d, IP is : %s, port : %d\n", new_socket, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); // Add new socket to set of file descriptors to monitor client_sockets[i] = new_socket; } // Main loop to monitor file descriptors for activity while (1) { // Clear the set of file descriptors to monitor FD_ZERO(&readfds); // Add server socket and client sockets to the set of file descriptors to monitor FD_SET(server_fd, &readfds); max_fd = server_fd; for (i = 0; i < MAX_CLIENTS; ++i) { sd = client_sockets[i]; if (sd > 0) { FD_SET(sd, &readfds); } if (sd > max_fd) { max_fd = sd; } } // Wait for activity on any of the monitored file descriptors activity = select(max_fd + 1, &readfds, NULL, NULL, NULL); if (activity < 0) { perror("select error"); exit(EXIT_FAILURE); } // If there is activity on the server socket, it means there is a new incoming connection if (FD_ISSET(server_fd, &readfds)) { new_socket = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t*)&addrlen); if (new_socket < 0) { perror("accept error"); exit(EXIT_FAILURE); } printf("New connection, socket fd is %d, IP is : %s, port : %d\n", new_socket, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); // Add new socket to set of file descriptors to monitor for (i = 0; i < MAX_CLIENTS; ++i) { if (client_sockets[i] == 0) { client_sockets[i] = new_socket; break; } } } // Check each client socket for activity for (i = 0; i < MAX_CLIENTS; ++i) { sd = client_sockets[i]; if (FD_ISSET(sd, &readfds)) { // Receive data from client valread = read(sd, buffer, BUFFER_SIZE); if (valread == 0) { // Client disconnected printf("Client disconnected, socket fd is %d\n", sd); close(sd); client_sockets[i] = 0; } else { // Display received data and send response back to client printf("Received data from client %d: %s\n", sd, buffer); send(sd, buffer, strlen(buffer), 0); } } } } return 0; } ``` 在上述代码中,我们首先创建了一个服务器套接字,然后将它绑定到指定的端口并开始监听。接着,在一个循环中,我们使用select函数来等待任何一个文件描述符上的活动,当有活动时,我们就处理该活动。如果是服务器套接字上的活动,说明有新的客户端连接,我们接受该连接并将其添加到要监听的文件描述符集合中。如果是客户端套接字上的活动,说明客户端已经发送数据,我们读取该数据并向客户端发送回复。如果客户端已经断开连接,我们将其从要监听的文件描述符集合中移除,并关闭该套接字。

相关推荐

最新推荐

recommend-type

C语言中send()函数和sendto()函数的使用方法

主要介绍了C语言中send()函数和sendto()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下
recommend-type

详解C语言中symlink()函数和readlink()函数的使用

主要介绍了详解C语言中symlink()函数和readlink()函数的使用,是C语言入门学习中的基础知识,需要的朋友可以参考下
recommend-type

C语言中数组作为函数的参数以及返回值的使用简单入门

主要介绍了C语言中数组作为函数的参数以及返回值的使用简单入门,这里以一维数组作为基本条件进行例子讲解,需要的朋友可以参考下
recommend-type

c语言文件操作常用函数及读写文件代码举列

文章主要例举一个c语言文件操作常用函数及读写文件的代码,感性趣的朋友可以看看。
recommend-type

socket多人聊天程序C语言版(一)

主要为大家详细介绍了socket多人聊天程序C语言版,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

用 Python 画一个可以动的爱心

好的,我可以帮助您使用Python来绘制一个动态的爱心。您可以使用turtle库来实现。以下是实现代码: ```python import turtle import math # 设置画布和画笔 canvas = turtle.Screen() canvas.bgcolor("black") pencil = turtle.Turtle() pencil.speed(0) pencil.color("red", "pink") pencil.pensize(3) # 定义爱心函数 def draw_love(heart_size, x_offset=0, y_offset=0):
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。