linux c++ select 学习

文章目录

前言

一、优缺点?

二、测试代码

1.服务端

2.客户端

三、执行结果及问题

四、问题修正

五、仍然存在的问题



前言

selec 和 pselect 可以同时监控多个多个文件描述符(I/O复用),包括STDIN,STDOU,socket 文件描述符等。等待一个或多个文件描述符状态变为准备状态(事件驱动)。


提示:本文所有代码只是测试用例,作为学习记录,请勿在项目代码中直接使用。

一、优缺点?

优点: 可以监控多个文件描述符。监控文件描述符较少的情况下,效率很高。

缺点:1. 每次调用select 都要需要把fd集合从用户态拷贝到内核态。性能损失

           2.  每次调用select都要要遍历从内核传递过的fd。

           3. 文件描述数量大小为1024。可以更改头文件typesizes.h 中 __FD_SETSIZE 宏大小更改.

二、测试代码

本测试是测试多客户端请求select服务端性能及问题,多个线程分别发送一定数量的包,服务端状态及接受状况。

1.服务端

#include <sys/select.h>
#include <stdio.h>
#include <time.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/types.h>
#include <vector>
#include <iostream>
#include <errno.h>
#include <string.h>
#include <atomic>
void setFdNoblock(int fd)
{
    fcntl(fd, O_NONBLOCK);
}
int main()
{
    std::vector<int> setlist;
    //setlinebuf(STDIN_FILENO);
    fd_set sets;
    FD_ZERO(&sets);
    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = INADDR_ANY;
    sa.sin_port = htons(12550);

    int st = socket(AF_INET, SOCK_STREAM, 0);
    if (st == -1)
    {
        printf("create socket error %s.\r\n", strerror(errno));
        exit(-1);
    }

    if (bind(st, (struct sockaddr *)&sa, sizeof(sa)) == -1)
    {
        printf("bind socket error %s.\n", strerror(errno));
        exit(-1);
    }

    if(listen(st, 1023) == -1)
    {
        printf("listen socket error %s.\n", strerror(errno));
        exit(-1);
    }
    volatile std::atomic<int> count(0);
    int maxfd = st;
    std::cout<<"server start."<<std::endl;
    int loopcount = 0;
    while (true)
    {
        loopcount++;
        FD_SET(st, &sets);
        for (auto i : setlist)
        {
            FD_SET(i, &sets);
        }
        int ocfd = select(maxfd + 1, &sets, NULL, NULL, NULL);
        if (FD_ISSET(st, &sets))
        {
            struct sockaddr_in client;
            socklen_t scsize = sizeof(client);
            int clientfd = accept(st, (struct sockaddr *)&client, &scsize);
            std::cout<<"client connect["<<inet_ntoa(client.sin_addr)<<"] connet."<<std::endl;
            fcntl(clientfd,F_SETFL,O_NONBLOCK);
            setlist.push_back(clientfd);
            if (maxfd < clientfd)
            {
                maxfd = clientfd;
            }
        }

        for (int i = 0; i < ocfd; i++)
        {
            for (auto i : setlist)
            {
                if (FD_ISSET(i, &
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值