【网络编程】select函数

select的优点是跨平台的,缺点是因为是轮询查询的,相对效率不高

使用 select 同时监听多个文件描述符, 将监控的操作交给内核去处理,当有监控操作时返回。select可以完成一个进程对多个客户端的处理

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds: 最大的文件描述符+1
readfds: 读文件描述符集合, 是一个传入传出参数,用于设置监听某些文件描述符的读操作,和返回有读操作的文件描述符集合。传入: 指的是告诉内核哪些文件描述符需要监控传出: 指的是内核告诉应用程序哪些文件描述符发生了变化
writefds: 写文件描述符集合(传入传出参数),同读文件描述符集合
execptfds: 异常文件描述符集合(传入传出参数),同读文件描述符集合
timeout: NULL--表示永久阻塞, 直到有事件发生0 --表示不阻塞, 立刻返回, 不管是否有监控的事件发生>0--到指定事件或者有事件发生了就返回The time structures involved are defined in <sys/time.h> and look likestruct timeval {long    tv_sec;         /* seconds */long    tv_usec;        /* microseconds */}返回值:  成功返回发生变化的文件描述符的个数失败返回-1, 并设置errno值.//初始化文件文件描述符集合
void FD_ZERO(fd_set *set);
//添加文件描述符到集合
void FD_SET(int fd, fd_set *set);
//将文件描述符从集合中删除
void FD_CLR(int fd, fd_set *set);
//判断文件描述符是否在集合中
int  FD_ISSET(int fd, fd_set *set);

使用select处理多个客户端网络代码:

#include "socketwrap.h"
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>int main()
{int sfd = Socket(AF_INET, SOCK_STREAM, 0);// 设置端口复用int opt = 1;setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));struct sockaddr_in soaddr;bzero(&soaddr, sizeof(soaddr));soaddr.sin_family = AF_INET;soaddr.sin_port = htons(9999);soaddr.sin_addr.s_addr = htonl(INADDR_ANY);Bind(sfd, (struct sockaddr *)&soaddr, sizeof(soaddr));// 监听-listenListen(sfd, 128);int connfd[FD_SETSIZE]; // 有效的文件描述符数组fd_set tmpfds, rdfds;   // 要监控的文件描述符集int maxfd;              // 当前需要监听的最大的文件描述符int nready;             // 返回的需要处理的个数int cfd;                // 通信描述符int i, maxi = 0;        // 通信描述符数组下标,及最大下标struct sockaddr_in clientsocket;socklen_t clilen;char buff[64]; // 通信数据FD_ZERO(&tmpfds);FD_ZERO(&rdfds);FD_SET(sfd, &rdfds);// 初始化有效的文件描述符数组for (int i = 0; i < FD_SETSIZE; i++){connfd[i] = -1;}maxfd = sfd;while (1){i = 0;clilen = sizeof(clientsocket);bzero(&clientsocket, clilen);tmpfds = rdfds;nready = select(maxfd + 1, &tmpfds, NULL, NULL, NULL);if (nready > 0){if (FD_ISSET(sfd, &tmpfds)){cfd = Accept(sfd, (struct sockaddr *)&clientsocket, &clilen);if (cfd < 0){break;}// 先找位置, 然后将新的连接的文件描述符保存到connfd数组中for (i = 0; i < FD_SETSIZE; i++){if (connfd[i] == -1){connfd[i] = cfd;break;}}// 若连接总数达到了最大值,则关闭该连接if (i == FD_SETSIZE){close(cfd);printf("too many clients, i==[%d]\n", i);// exit(1);continue;}// 确保connfd中maxi保存的是最后一个文件描述符的下标if (i > maxi){maxi = i;}// 打印客户端的IP和PORTchar sIP[16];memset(sIP, 0x00, sizeof(sIP));printf("client [%s:%d] connect\n", inet_ntop(AF_INET, &clientsocket.sin_addr.s_addr, sIP, sizeof(sIP)), htons(clientsocket.sin_port));FD_SET(cfd, &rdfds);if (maxfd < cfd){maxfd = cfd;}// 若没有其他变化的文件描述符,则无需执行后续代码if (--nready <= 0){continue;}}for (i = 0; i <= maxi; i++){int sockfd = connfd[i];if (sockfd == -1){continue;}int n;if (FD_ISSET(sockfd, &tmpfds)){memset(buff, 0x00, sizeof(buff));n = Read(sockfd, buff, sizeof(buff));if (n < 0){perror("read over");close(sockfd);FD_CLR(sockfd, &rdfds);connfd[i] = -1; // 将connfd[i]置为-1,表示该位置可用}else if (n == 0){// printf("client is closed\n");close(sockfd);FD_CLR(sockfd, &rdfds);connfd[i] = -1; // 将connfd[i]置为-1,表示该位置可用}else{printf("[%d]:[%s]\n", n, buff);for (i = 0; i < n; i++){buff[i] = toupper(buff[i]);}Write(sockfd, buff, n);}if (--nready <= 0){break; // 注意这里是break,而不是continue, 应该是从最外层的while继续循环}}}}}close(sfd);return 0;
}

推荐一个零声教育学习教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/46273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Python thinker GUI界面的股票评论数据及投资者情绪分析设计与实现

1.绪论 1.1背景介绍 Python 的 Tkinter 库提供了创建用户界面的工具&#xff0c;可以用来构建股票评论数据及投资者情绪分析的图形用户界面&#xff08;GUI&#xff09;。通过该界面&#xff0c;用户可以输入股票评论数据&#xff0c;然后通过情感分析等技术对评论进行情绪分析…

前端数据加密方式

1、Base64加密 一、原生加解密 const btoa window.btoa(123) // 编码console.log(加密后,btoa)const atob window.atob(bota) // 解码console.log(解密后,atob) 二、base64插件 npm install --save js-base64 <script lang"ts"> import { defineCompon…

JavaScript 中 await 永远不会 resolve 的 Promise 会导致内存泄露吗?

前言 在 JavaScript 中&#xff0c;await 关键字用于等待一个 Promise 完成&#xff0c;它只能在异步函数&#xff08;async function&#xff09;内部使用。当 await 一个永远不会 resolve 的 Promise 时&#xff0c;它确实会阻塞异步函数的进一步执行&#xff0c;但不会直接…

Matlab中产生高斯白噪声信号的方法和其功率计算

Matlab中产生高斯白噪声信号的方法和其功率计算 matlab中计算信号能量&#xff1a; p o w e r ∑ n 1 N x 2 ( n ) power \sum_{n1}^Nx^2(n) powern1∑N​x2(n) ​ 功率为 P 1 N ∑ n 1 N x 2 ( n ) P \frac{1}{N}\sqrt{\sum_{n1}^Nx^2(n)} PN1​n1∑N​x2(n) ​ 对应ma…

C1W1.Assignment: Logistic Regression

理论课&#xff1a;C1W1.Sentiment Analysis with Logistic Regression 文章目录 前期准备导入包导入数据处理推文文本 Part 1: Logistic regressionPart 1.1: Sigmoid实现 sigmoid 函数Logistic regression: regression and a sigmoid Part 1.2 Cost function and GradientUp…

Python 使用proto 发送socket数据

import socket import binascii import struct from SensingMonitoring_pb2 import Command, CommandNamesif __name__ "__main__":client socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(("192.168.1.100", 22295))# 发送数据comman…

软件模块的初始化

什么是初始化&#xff1f; 软件的初始化&#xff08;Initialization&#xff09;是指软件启动或重新配置时执行的一系列步骤和过程&#xff0c;旨在准备软件运行环境、加载必要的配置信息、检查系统依赖项、分配资源&#xff08;如内存、文件句柄等&#xff09;&#xff0c;以及…

Microsoft Build 2024 推出 .NET 9:Tensor<T>、 OpenAI Collaboration和.NET Aspire

在 Microsoft Build 2024 上&#xff0c;.NET 9 4 发布&#xff0c;引入了用于深度学习的 Tensor 类型以及与 OpenAI Collaboration实现GPT4o和Assistants v2等功能。这些最新改进还带来了 .NET Aspire&#xff0c;简化了云原生应用开发。更新涵盖 ASP.NET Core、Blazor 和 .NE…

5、Hacker_Kid-v1.0.1

中等难度 目标root权限 先进行一波IP地址发现 netdiscover -i eth0 -r 192.168.1.1/24 发现存在的靶机ip 进行一波端口的探测 发现是一个apache的服务和一个tornado的网站 这里有个细节部分&#xff0c;53端口常见的情况都是走的udp协议做的域名解析&#xff0c;这里查询出来…

【ARM】CCI缓存一致性整理

目录 1.CCI500提供的功能 2.CCI500在SOC系统中所处的位置​编辑 3.CCI500内部结构​编辑 4.功能描述 1.CCI500提供的功能 2.CCI500在SOC系统中所处的位置 3.CCI500内部结构 Transaction Tracker&#xff08;TT&#xff09;是用来解决一致性和ordering问题的&#xff0c;它…

完成SSH连接与端口映射并运行hello_world.py以及创建conda环境

完成SSH连接与端口映射并运行hello_world.py 第一步&#xff1a; 使用vscode打开连接开发机如图 第二步&#xff1a; 端口映射 ssh -p 37367 rootssh.intern-ai.org.cn -CNg -L {本地机器_PORT}:127.0.0.1:{开发机_PORT} -o StrictHostKeyCheckingno 如&#xff1a; ssh -…

牛客周赛51 F(静态区间最大连续子段和)

题面 题目地址 原题是SPOJ 1043。本文中我介绍的是维护前缀和的写法&#xff0c;如果你想要了解其他写法&#xff0c;可以搜索原题题解。 题目大意&#xff1a; 给定长度为n的数组a&#xff0c;q次查询&#xff0c;每次询问[l,r]中连续子段和的绝对值最大是多少 1 < n, q&l…

SpringBoot整合 Kaptcha 验证码

文章目录 1 Kaptcha 验证码1.1 引言1.2 Kaptcha1.2.1 pom.xml1.2.2 配置类1.2.2.1 Redis配置类RedisConfig1.2.2.2 验证码配置类KaptchaConfig 1.2.3 验证码控制层1.2.4 登录控制层 1 Kaptcha 验证码 1.1 引言 为防止验证系统被暴力破解&#xff0c;很多系统都增加了验证码效…

优化静止不动的GPS点(JS版)

1.理论依据: 连续的GPS点中&#xff0c;静止不动的一段或者多段这样的点序列。把这些点序列处理成一个点&#xff0c;也就是拿这些序列的第一个点即可。理论依据如下&#xff1a;从第二个点开始&#xff0c;每个点都和第一个点进行距离计算和比较。至少比较N个点。当百分之M的…

maven多模块项目打包构建的配置

使用背景&#xff1a; springbootmaven构建的多模块项目&#xff0c;没有使用springcloud&#xff0c;根项目下有多个module&#xff0c;一个module有springboot启动类&#xff0c;其他module没有启动类&#xff0c;作为module被有springboot启动类的module所引用。 1.根目录…

Win11任务栏当中对 STM32CubeMX 的堆叠问题

当打开多个 CubeMX 程序的时候&#xff0c;Win11 自动将其进行了堆叠&#xff0c;这时候就无法进行预览与打开。 问题分析&#xff1a;大部分ST的工具都是基于 JDK 来进行开发的&#xff0c;Win11 将其识别成了同一个 Binary 但是实际上他们并不是同一个&#xff0c;通过配置…

redis源码分析之底层数据结构(一)-动态字符串sds

1.绪论 我们知道redis是由c语言实现的&#xff0c;c语言中是自带字符串的&#xff0c;但是为什么redis还要再实现自己的动态字符串呢&#xff0c;这种动态字符串的底层数据结构是怎样的呢?接下来我们带着这些问题来看一看redis中的动态字符串sds。 2.sds的组成 struct __at…

pico+unity3d项目配置

重点&#xff1a;unity编辑器版本要和pico的sdk要求一致、比如&#xff1a; 对于 Unity 2022.1.14 及以上版本&#xff0c;若同时在项目中使用 URP、Linear 色彩空间、四倍抗锯齿和OpenGL&#xff0c;会出现崩溃。该问题待 Unity 引擎解决。对于 Unity 2022&#xff0c;若同时…

多个版本JAVA切换(学习笔记)

多个版本JAVA切换 很多时候&#xff0c;我们电脑上会安装多个版本的java版本&#xff0c;java8&#xff0c;java11&#xff0c;java17等等&#xff0c;这时候如果想要切换java的版本&#xff0c;可以按照以下方式进行 1.检查当前版本的JAVA 同时按下 win r 可以调出运行工具…