Linux Select

Linux Select

 

在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核:

      •我们所关心的文件描述符
      •对每个描述符,我们所关心的状态。(我们是要想从一个文件描述符中读或者写,还是关注一个描述符中是否出现异常)
      •我们要等待多长时间。(我们可以等待无限长的时间,等待固定的一段时间,或者根本就不等待)
   从 select函数返回后,内核告诉我们一下信息:
      •对我们的要求已经做好准备的描述符的个数
      •对于三种条件哪些描述符已经做好准备.(读,写,异常)

select
——用于IO多路复用
(1)函数原型

#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout);

(2)参数
        n:最大的文件描述词加1;
        readfds、writefds 和exceptfds:称为描述词组,是用来回传该描述词的读,写或例外的状况;
        timeout:用来设置select()的等待时间。

struct timeval
{time_t tv_sec;time_t tv_usec;
};

(3)返回值
        如果参数timeout设为NULL则表示select()没有timeout。
执行成功则返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间,当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds和timeout的值变成不可预测。
EBADF 文件描述词为无效的或该文件已关闭
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。

ENOMEM 核心内存不足

常见的程序片段:fs_set readset;
FD_ZERO(&readset);
FD_SET(fd,&readset);
select(fd+1,&readset,NULL,NULL,NULL);
if(FD_ISSET(fd,readset){……}
#ifndef _SELECT_H_
#define _SELECT_H_#include "wrap.h"
#include "client_list.h"
#include "server_queue.h"#define SERVER_PORT     6780
#define MAXLINE         100
#define OPEN_MAX        65535
#define TCP_FRAME_SIZE  1200typedef struct
{int sockfd;  // server socketint port;    // server portstruct sockaddr_in addr; // server addrint maxi;  // select maxint maxfd;int aggregate[FD_SETSIZE];// select aggregationfd_set allset;server_queue_t send_queue; // server send data queue to clientserver_queue_t recv_queue; // server recv data queue from clientpthread_t send_thread;pthread_t recv_thread;client_t *client;  // client list -- save all client info
} server_t;/* recv and send queue frame */
typedef struct
{int sockfd;  // client socketuint16_t length;char data[TCP_FRAME_SIZE];
} __packed tcp_frame_t;//==========================================================
server_t *SocketInit(void);#endif /* _SELECT_H_ */
#include "select.h"
#include "debug.h"static server_t *socket_init(void)
{int opt = 1, i;server_t *current;current = (server_t *)malloc(sizeof(server_t));current->port = SERVER_PORT;current->sockfd = Socket(AF_INET, SOCK_STREAM, 0);// SOL_SOCKET: port can same, ip notSetsockopt(current->sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));current->addr.sin_family = AF_INET;current->addr.sin_port = htons(current->port);current->addr.sin_addr.s_addr = INADDR_ANY;Bind(current->sockfd, (struct sockaddr *)&current->addr, sizeof(current->addr));Listen(current->sockfd, MAXLINE);current->maxi = -1;current->maxfd = current->sockfd;for(i = 0; i < FD_SETSIZE; ++i){current->aggregate[i] = -1;}FD_ZERO(current->allset);FD_SET(current->sockfd , current->allset);ServerQueueInit(&current->send_queue, TCP_FRAME_SIZE);ServerQueueInit(&current->recv_queue, TCP_FRAME_SIZE);return current;
}static void socket_accept(server_t *arg, fd_set *rset)
{server_t *current = arg;struct sockaddr_in addr;int len = sizeof(struct sockaddr_in), i;int new_fd = Accept(current->sockfd, (struct sockaddr *)&addr, &len);debug("new connection client_fd ( %d ) %s: %d\n", new_fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));for(i = 0; i < FD_SETSIZE; ++i){if(current->aggregate[i] < 0){// add new_fd to aggregatecurrent->aggregate[i] = new_fd;break;}}if(FD_SETSIZE == i){printf("too many connects\n");Close(new_fd);return;}FD_SET(new_fd , current->allset);if(new_fd > current->maxfd){current->maxfd = new_fd;}if(i > current->maxi){current->maxi = i;}/* add client node */client_t *node = (client_t *)malloc(sizeof(client_t));node->sockfd = new_fd;memcpy(&node->addr, &addr, sizeof(struct sockaddr_in));ClientAdd(node);
}static void socket_recv(server_t *arg, fd_set *rset, int ret)
{server_t *current = arg;int i, sockfd, length = 0;tcp_frame_t write;for(i = 0; i <= current->maxi; ++i){if((sockfd = current->aggregate[i]) < 0){continue;}if(FD_ISSET(sockfd , rset)){length = recv(sockfd, write.data, TCP_FRAME_SIZE, 0);if(0 == length){/* delete client node, close connect socket */debug("client[%d] close\n", sockfd);ClientDel(sockfd);Close(sockfd);FD_CLR(sockfd , current->allset);current->aggregate[i] = -1;continue;}else if(length > 0){write.sockfd = sockfd;write.length = length;server_debug(write.data, write.length);// add data to recv_queue, pop in other,if(ServerQueueWrite(&current->recv_queue, (uint8_t *)&write, sizeof(tcp_frame_t)) == 0){debug("push failure...queue full...\n");}}if(--ret <= 0){break;}}}
}static void *server_recv_thread(void *arg)
{server_t *current = (server_t *)arg;fd_set rset;struct timeval timeout;while(1){rset = current->allset;timeout.tv_sec = 0;timeout.tv_usec = 200;int ret = Select(current->maxfd + 1 , &rset, NULL , NULL , &timeout);if(0 == ret){continue;}if(FD_ISSET(current->sockfd, &rset)){socket_accept(current, &rset); // a new connect come}if(--ret < 0){continue;}socket_recv(current, &rset, ret); // a exsit connect send data to us}Close(current->sockfd);return NULL;
}static void *server_send_thread(void *arg)
{server_t *current = (server_t *)arg;tcp_frame_t *read = NULL;while(1){//read = (tcp_frame_t*)ServerQueueRead(&current->send_queue, sizeof(tcp_frame_t));if(read != NULL){//server_debug(read->data, read->length);}usleep(100);}return NULL;
}server_t * SocketInit(void)
{server_t *current = socket_init();debug("create thread...\r\n");pthread_create(&current->send_thread, NULL, server_send_thread, current);pthread_create(&current->recv_thread, NULL, server_recv_thread, current);return current;
}

 

 

 

 

 

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

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

相关文章

搞懂图像二值化算法

传统的机器视觉通常包括两个步骤&#xff1a;预处理和物体检测。而沟通二者的桥梁则是图像分割&#xff08;Image Segmentation&#xff09;[1]。图像分割通过简化或改变图像的表示形式&#xff0c;使得图像更易于分析。举个例子&#xff0c;食品加工厂新进了一批肉鸡&#xff…

JavaWeb无限级分销结构分析

在现实生活中我们经常遇到由推荐人注册&#xff0c;比如一个购物平台,用户A推荐用户B注册&#xff0c;那当B购买商品成功时&#xff0c;用户A就会拿到相应的提成。只要是用户A推荐的用户购买商品成功后&#xff0c;A用户都会拿到提成。 当用户B推荐了用户C&#xff0c;那当用户…

一个风骚的C语言操作

有个小伙伴在我们的嵌入式交流群里发了类似下面的一张图&#xff0c;顿时引起一阵骚动&#xff0c;我把源代码再附上&#xff0c;main.c 如下&#xff1a;#include <stdio.h> #include <string.h>static char city_name[][20] { #include "city.h" };in…

SQL Server表分区-水平分区

SQL Server表分区&#xff0c;sql server水平分区 转自&#xff1a;http://www.cnblogs.com/knowledgesea/p/3696912.html 根据时间的&#xff0c;直接上T-SQL代码的水平分区&#xff1a;https://www.xuebuyuan.com/1817312.html?tdsourcetags_pcqq_aiomsg什么是表分区 一般情…

基于STC89C52的韦根数据接收

韦根是一种开放的通讯协议&#xff0c;具体官方介绍如下&#xff1a;Wiegand协议是国际上统一的标准&#xff0c;有很多格式&#xff0c;标准的26-bit 应该是最常用的格式。此外&#xff0c;还有34-bit 、37-bit 等格式。格式的含义如下&#xff1a;当给出这一串数字&#xff0…

超乎想象,数据揭示自学成才的码农为何备受青睐

你是否想成为一个 Web 开发者&#xff0c;但却不知道从哪里开始&#xff1f; 你是否对学习编程语言的大量建议和繁琐细节感到审美疲劳&#xff1f; 你是否不确定需要遵循哪条路才能成为一个自信而又足智多谋的开发者&#xff1f; 如果你的回答是肯定的&#xff0c;那么不要担心…

Linux下的图形库curses写贪吃蛇,酷

最近看到大神在Linux下写的贪吃蛇代码&#xff0c;用到了curses图形库&#xff0c;可能很多人都没有用过&#xff0c;分享出来给大家。在ubuntu下安装curses图形库命令sudo apt-get install libncurses5-dev双buff是一个非常优秀的机制&#xff0c;之前写贪吃蛇的时候&#xff…

初中变成了菜园子了!

我家在四川省射洪县天仙镇凤鸣场&#xff0c;属于四川盆地山区&#xff0c;在四川中部&#xff0c;发源于川北羌塘群山的涪&#xff08;fu&#xff09;江流经射洪县城。天仙镇原名天仙寺&#xff0c;附近很多乡镇都是奇怪的名字&#xff1a;大庙、双庙、佛照、玉贞观。我怀疑这…

单片机数字滤波算法如何实现?(附代码)

ID&#xff1a;技术让梦想更伟大整理&#xff1a;李肖遥单片机主要作用是控制外围的器件&#xff0c;并实现一定的通信和数据处理。但在某些特定场合&#xff0c;不可避免地要用到数学运算&#xff0c;尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是介绍如何用单片机…

利用云计算打造政务信息化及应急指挥云平台

本文转载自星光云http://www.365yun.top/news/list.asp?newsid24云计算平台提供最全面的、集成度最高的开放平台&#xff0c;构建和管理面向运营、运维、用户服务的云数据中心管理平台&#xff1b;需集成计算、存储、网络、安全及管理&#xff0c;能够提供满足从基础设施到应用…

项目实战,平均负载过高,最后发现却是这个搞鬼

1.前言最近在项目上遇到负载均衡过高的问题&#xff0c;分析好几天&#xff0c;还因此移植了一个CPU检测工具&#xff0c;后面在小二哥的指导找到了问题原因&#xff0c;小二哥有些读者应该会比较熟悉&#xff0c;之前发的微信滑动卡顿就是他分析的&#xff0c;他是一个非常厉害…

虚拟机压缩

virtualbox虚拟机运行久了之后就会发现&#xff0c;磁盘镜像vdi文件越来越大。即使你把虚拟机中的大文件删除&#xff0c;这个vdi文件占用的空间还是不变。也就是说动态扩展的vdi文件只会大&#xff0c;不会小。那么大的文件对于备份和分享都不是很方便&#xff0c;所以有必要的…

QT——QT4.8.5安装与配置

Qt4.8.5安装 1、安装包 mingw32-4.4.0.7z qt-creator-windows-opensource-2.8.0.exe qt-win-opensource-4.8.5-mingw.exe 2、安装步骤 &#xff08;1&#xff09;、首先安装qt creator,双击qt-creator-windows-opensource-2.8.0,注意安装目录不要有空格和特殊字符, 假设安装…

Linux中,文件创建的时间是怎么保存的?

今天在微信群里有人提问&#xff0c;如果创建一个文件&#xff0c;创建这个文件的时间是保存在哪里的。所以就查到了这篇文章。在介绍inode结构体之前先做一个链接文件的实验&#xff1a;1.创建一个普通的文件test.txt&#xff0c;并写入内容查看&#xff0c;如下2.创建test.tx…

神琪宝贝

团队名称&#xff1a;神琪宝贝团队人员&#xff1a; 姓名&#xff1a;温广琪&#xff08;组长&#xff09;学号&#xff1a;1600802130博客&#xff1a;http://www.cnblogs.com/wenwenwgq/技术&#xff1a;C&#xff0c;Java&#xff0c;python&#xff0c;网站兴趣&#xff1a…

汇顶科技2021秋招笔试

来源于读者投稿&#xff0c;作者Angel。笔试时间&#xff1a;2020.08.24&#xff0c;20&#xff1a;00-21&#xff1a;00提醒&#xff1a;很多大公司秋招在七八月份就要投递简历&#xff0c;九月已经晚了。题型&#xff1a;通用部分单选10道 不定项选择题2道 填空题2道 开放题目…

科大讯飞2021笔试题

来源于读者投稿&#xff0c;作者Angel笔试时间&#xff1a;2020.09.12,19&#xff1a;00——21&#xff1a;00岗位&#xff1a;嵌入式软件开发题型&#xff1a;四道编程题&#xff0c;4*1040分题目1、定义一个n*m矩阵&#xff0c;找到两个不在同一行同一列的数字&#xff0c;使…

跨交换机VLAN配置

CCNP实验之&#xff08;跨交换机VLAN&#xff09;<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />跨交换机设置原则:存在一台VLAN服务器&#xff0c;可以存在多台vlan客户端&#xff0c;那么需要配置VTP域。交换机的连接需干线&…

详细记录丨Realtek RTL8188FU WiFi 驱动移植

1 参考资料 1、芯片数据手册&#xff1a;TL8188FCA.pdf2、驱动移植手册&#xff1a;Quick_Start_Guide_for_Driver_Compilation_and_Installation.pdf3、【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.3.pdf4、Linux 添加 WiFi 驱动&#xff1a;https://blog.csdn.net/sbddbfm/…

拆解1968年的美国军用电脑,真的怀疑是“穿越”啊!

来源&#xff1a;数码之家文 | 禅哥这台机器在本人的eBay收藏夹里呆了很久&#xff0c;某日无意间扫了一眼收藏夹&#xff0c;突然发现卖家大降价&#xff0c;只要15刀&#xff0c;还有best offer选项。15刀你买不了吃亏&#xff0c;15刀你买不了上当。事不宜迟果断下手。根据非…