您的位置:首页 > 健康 > 养生 > 企业网站优化推广方法_北京网站开发公司_网络营销员岗位的职责与要求_可以免费发外链的论坛

企业网站优化推广方法_北京网站开发公司_网络营销员岗位的职责与要求_可以免费发外链的论坛

2024/12/22 9:36:32 来源:https://blog.csdn.net/asdzccfrew/article/details/143403747  浏览:    关键词:企业网站优化推广方法_北京网站开发公司_网络营销员岗位的职责与要求_可以免费发外链的论坛
企业网站优化推广方法_北京网站开发公司_网络营销员岗位的职责与要求_可以免费发外链的论坛

select函数、I/O复用、并发服务器

select函数原型

extern int select (int __nfds, fd_set *__restrict __readfds,fd_set *__restrict __writefds,fd_set *__restrict __exceptfds,struct timeval *__restrict __timeout);

参数介绍:

  1. int __nfds:
  • 这是需要监视的文件描述符集合中最大的文件描述符值加1。因为文件描述符是从0开始分配的,所以如果你有文件描述符3,那么你实际上是在监视0, 1, 2, 和3这四个文件描述符(尽管可能其中一些并没有被使用)。因此,这个参数应该设置为4(即最大文件描述符+1)。
    操作fe_set集合统一的宏来处理:
    • FD_SET(fd, &set): 将文件描述符fd添加到set集合中。
    • FD_CLR(fd, &set): 从set集合中删除文件描述符fd。
    • FD_ISSET(fd, &set): 检查fd是否在set集合中。
    • FD_ZERO(&set): 清空set集合。
  1. fd_set *__restrict __readfds:
  • 这是一个指向文件描述符集合的指针,该集合中的文件描述符被监视以查看它们是否可读。如果不需要监视任何文件描述符是否可读,这个参数可以设置为NULL。
  1. fd_set *__restrict __writefds:
  • 类似于 __readfds,这个参数指向一个文件描述符集合,集合中的文件描述符被监视以查看它们是否可写。如果不需要监视任何文件描述符是否可写,这个参数可以设置为NULL。
  1. fd_set *__restrict __exceptfds:
  • 这也是一个指向文件描述符集合的指针,集合中的文件描述符被监视以查看是否有异常条件发生(比如带外数据到达)。如果不需要监视任何文件描述符的异常条件,这个参数可以设置为NULL。
  1. struct timeval *__restrict __timeout:
  • 这是一个指向 timeval 结构体的指针,该结构体指定了 select 函数等待的最长时间。如果设置为NULL,select 将无限期地等待,直到某个文件描述符准备好。
  • timeval 结构体通常包含两个成员:tv_sec(秒)和 tv_usec(微秒),用于指定时间间隔。
  1. 返回值:
  • select 函数返回准备好的文件描述符的总数(即可读、可写或有异常条件的文件描述符总数)。
  • 如果返回-1,则表示发生了错误(此时应该检查 errno 来确定错误的具体原因)。
  • 如果返回0,这表示超时。

可以直接看使用实例:可以使用任意客户端代码进行测试


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/select.h>#define LISTEN_NUM 10void error_handing(char *message)
{fputs(message,stderr);fputc('\n',stderr);exit(1);
}
int main(int argc, char const *argv[])
{//步骤1:创建套接字int server_sock;server_sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);if (server_sock == -1){error_handing("socket() error");}//步骤2:绑定监听端口struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(atoi("3333"));if (bind(server_sock,(struct sockaddr *)&server_addr,sizeof(server_addr)) == -1){error_handing("bind() error");}//步骤3:开启监听if (listen(server_sock,LISTEN_NUM) == -1){error_handing("listen() error");}//步骤4:做select调用之前的准备//步骤4.1:初始化sock 集合fd_set fd_reads,fd_copy;//经过select函数之后,需要比较fd_set中的位是否改变,所以这里总是需要两个fd_set变量FD_ZERO(&fd_reads);//步骤4.2:将server_sock加入到集合中FD_SET(server_sock,&fd_reads);//步骤4.3:初始化最大值int fd_max = server_sock;//定义最大的socketwhile (1){fd_copy = fd_reads;//步骤4.4:设置超时时间struct timeval time_out;time_out.tv_sec = 5;//步骤5:调用select函数,讨论其返回值int activity_sockets = select(fd_max + 1,&fd_copy,NULL,NULL,&time_out);if (activity_sockets == -1)//发生错误,退出{error_handing("select() error");}else if (activity_sockets == 0)//超时{//选择继续运行printf("Time out.\n");continue;}for (size_t i = 0; i < fd_max + 1; i++)//比较是否对应的事件位是否改变{if (FD_ISSET(i,&fd_copy))//说明i事件活动了{   if(i == server_sock)//说明有新的客户端接入{printf("New client connected...\n");struct sockaddr client_addr;int sizeof_client_addr = sizeof(client_addr);int client_sock = accept(server_sock,&client_addr,&sizeof_client_addr);//将客户端的socket加入到总的fd_set中,就可以使用select查询处理FD_SET(client_sock,&fd_reads);//更新最大值,因为select监听的sockt是从0~fd_max  fd_max = (client_sock > fd_max) ? client_sock : fd_max;}else//说明有客户端数据进来{const int message_size = 30;char message[message_size];int read_size;read_size = read(i,message,message_size);if (read_size == 0)//说明客户端请求关闭连接{printf("Close client...\n");FD_CLR(i,&fd_reads);//踢出监控集合close(i);//再关闭连接}else//收到数据,选择给它回发过去{message[read_size] = '\0';printf("Receive message is %s.\n",message);write(i,message,read_size);}}} }  }close(server_sock);return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com