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…

vs2015无法打开包括文件:“winapifamily.h”

老项目是vs2003下的项目。升级vs2015后&#xff0c;调试运行报错 C:\Program Files (x86)\Windows Kits\8.0\Include\um\winsdkver.h(21): fatal error C1083: 无法打开包括文件:“winapifamily.h”: No such file or directory 在项目包含目录中包含了这个Windows Kits\8.0\…

JavaWeb无限级分销结构分析

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

如何在Word里面自动生成目录

1、对整个文本进行排版处理&#xff1b; 2、先将第一个一级标题选中&#xff0c;再点击工具栏“字体”前“正文”的下拉菜单&#xff0c;选择“标题1”&#xff1b; 3、此时会在此行前出现一个黑点&#xff0c;表明此行已被设为目录项&#xff08;前方黑点不会被打印&#xff0…

一个风骚的C语言操作

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

VS2003升级VS2010修改

BUG1: fatal error C1189: #error: MFC does not support WINVER less than 0x0601. Ple 在StdAfx.h中把#define WINVER 0X0500 //为 Windows98 和 Windows 2000 及更新版本改变为适当的值。改为&#xff1a; #define _WIN32_WINNT 0x0601 BUG2: https://www.cnblogs.com/slo…

Linux poll

Linux poll poll提供的功能与select类似&#xff0c;不过在处理流设备时&#xff0c;它能够提供额外的信息。 1、函数原型#include <poll.h>int poll(struct pollfd fd[], nfds_t nfds, int timeout);2、函数参数&#xff1a;&#xff08;1&#xff09;fd&#xff1a;一个…

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什么是表分区 一般情…

jQuery1.3.2 源码学习 -2 两个重要的正则表达式

32 // Is it a simple selector 33 isSimple /^.[^:#\[\.,]*$/ / / 表示这是正则表达式 ^ 表示开始部分 $ 表示结束部分 . 匹配除了 \n 之外的任何字符 [^character_group] 表示不在字符集合中 [^:#\[\.,] 表示除了冒号 (:), #, 前中括号([), 句号(.) 和逗号(,)之外的任何一个…

基于STC89C52的韦根数据接收

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

头文件介绍

头文件介绍 axftmp1.h 是收集类模板(MFC模板类)的头文件&#xff0c;倘若你在程序中用到了CArray, CObList等数据结构时&#xff0c;那么就得加载该文件。通常在MFC编程中&#xff0c;为了使用集合、数组类&#xff0c;要在StdAfx.h中加入下面语句&#xff1a;#include <afx…

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

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

Linux epoll

Linux epoll事件触发一、什么是epollepoll是什么&#xff1f;按照man手册的说法&#xff1a;是为处理大批量句柄而作了改进的poll。当然&#xff0c;这不是2.6内核才有的&#xff0c;它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linuxkernel 2.5.44)&…

Cisco 3层交换HSRP

现在3层交换机上:先把每一台交换机的vlan的ip配好在进入vlan (n)下在配<一>热备份的ip<二>配优先级(standby 加是第几组如1 priority 加优先级 如200)<三>占先权(standby 1 preempt)配置如下:假如你是vlan1ip routinginterface vlan 1standby 1 ip 192.168.1…

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

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

BUG笔记

1.无法打开lib 你这个 error LNK1104是链接时的错误&#xff0c;应该是需要此库&#xff0c;没办法忽略 找到此库 并在Properties->Linker->Input->Additional Depenncidees里加入库名 在Properties->Linker->General->Additional Library Directories里加入…

STM32f103C8T6 bootloader设计

STM32 bootloader设计 使用的是STM32f103C8T6&#xff1a;64Kflash&#xff0c;在应用程序中通过CAN把接受到的bin写到外置 flash的指定地址处。在bootloader中判断一个单独的标志位看程序是否需要升级&#xff0c;如果需要升级&#xff0c;则复制外置flash处的内容到STM32的内…

初中变成了菜园子了!

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

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

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

VS2010,C++ 制作静态库(*.lib),并使用

VS2010,C 制作静态库(*.lib)&#xff0c;并使用 原文链接&#xff1a;https://blog.csdn.net/qq_41472037/article/details/100001322 简单来说&#xff0c;就是建立两个项目:① Win32 Project &#xff08;Win32 项目&#xff09;&#xff1a; 接口文件.h 和 实现接口文件.cp…