select和poll的使用

1)select的源码案例
//fcntl函数的作用:可以用fcntl函数改变一个已打开的文件属性而不必重新open文件;
//什么叫IO多路复用,一个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),
//->则能够通知应用程序进行相应的读写操作;
//select用3个位图表示3个fdset的方式,poll使用一个pollfd的指针实现;
//io函数两种职责:操作IO和检测IO;
//基于事件网络模型 = 非阻塞IO + io多路复用;非阻塞IO的职责是只操作具体的IO,IO多路复用的职责是检测IO;
//检测功能放到内核中,包括(select poll epoll等)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include

using namespace std;
int main(void)
{
    fd_set fset;
    int fd = 0; //默认fd为输入,所以设置为0;
    int nread = 1024;
    int readNum = 0;
    char buffer[128];    
    FD_ZERO(&fset);
    FD_SET(fd,&fset);
    while(1)
    {        
        int ret = select(FD_SETSIZE,&fset,NULL,NULL,0);
        memset(buffer,0,sizeof(buffer));        
        switch(ret)
        {
            case -1:
                std::cerr<<"select error"<<std::endl;
            case 0:
                std::cout<<"select timeout"<<std::endl;
            default:
                if(FD_ISSET(fd,&fset))
                {
                    readNum = read(fd, buffer, nread); //必须读走,否则数据一直在缓存,造成select一直触发;
                    ioctl(fd, FIONREAD, &nread); //这句话必须有,否则不能在终端正确打印                      
                    if(readNum != 0)
                    {
                        // ioctl(fd, FIONREAD, &nread); //这句话不能在这里出现,否则不能正常打印;      
                        printf("receive num is: %d, recv msg is: %s",readNum,buffer);
                    }
                }
        }
    }
    return 0;
}

2)hash_map和map的【插入时间】运行时间比较,测试代码如下:

#include
#include
#include
#include
#include //注意添加这个头文件
#include
#include

using namespace std;
 
typedef hash_map<int,int> h_map_t;
typedef map<int,int> map_t;

int main()
{   
    h_map_t m1;
    map_t m2;
    time_t rawtime;
    struct tm * timeinfo;
    int start,end;

    time(&rawtime);
    timeinfo = localtime(&rawtime);
    start =  timeinfo->tm_sec;
    for(uint64_t i = 0; i < 5000000; i++)
    {
       m1.emplace(i,i);
    }
    time(&rawtime);    
    timeinfo = localtime(&rawtime);
    end =  timeinfo->tm_sec; 
    cout<<"hash_map container using time is: "<<end-start<<endl;       

    time(&rawtime);
    timeinfo = localtime(&rawtime);
    start =  timeinfo->tm_sec;
    for(uint64_t i = 0; i < 10000000; i++)
    {
       m2.emplace(i,i);
    }
    time(&rawtime);    
    timeinfo = localtime(&rawtime);
    end =  timeinfo->tm_sec;    
    cout<<"map container using time is: "<<end-start<<endl;
    return 0;
}

//输出结果如下:
hash_map container using time is: 2 second
map container using time is: 12 second
//结论:数据量较小的时候,可以选择map; 数据量大,对插入时间要求高的时候选择hash_map;
3)std::promise与std::future

1)std::promise与std::future用法1
#include 
#include 
#include 
 
#include "threadpool.h"
using namespace std;

void add(int a,int b, std::promise<int>& tmp_ret)
{
    int ret = a + b;
    tmp_ret.set_value(ret);
}
int main()
{
    std::promise<int> pro; //将promise作为一个参数,传递到线程当中去
    std::future<int> ret = pro.get_future();
    std::thread t(add,3,5,std::ref(pro)); 
    t.join();
    cout<<ret.get()<<endl;    
    return 0;
})std::promise与std::future用法2
//ret_future这里用的是引用类型
void add(int a,std::future<int>& ret_future, std::promise<int>& tmp_ret) 
{
    int ret = a + ret_future.get();
    tmp_ret.set_value(ret);
}
//主线程赋值,子线程获取
int main()
{
    std::promise<int> pro;
    std::future<int> ret = pro.get_future();

    std::promise<int> pro_in; 
    std::future<int> future_in = pro_in.get_future();

    std::thread t(add,3,std::ref(future_in),std::ref(pro)); 
    //do something 
    //...........
    //获取一个值,如下所示:
    pro_in.set_value(3);//假使这3是经过计算出来的,后经过赋值,把这个值传给子线程
    // future_in = pro_in.get_future();//不能有这句话,获取完,不能再获取了
    cout<<ret.get()<<endl;    
    t.join();
    return 0;
}

4)poll的使用案例

//poll的实现案例:
#include 
#include 
#include 
int main()
{
    struct pollfd rfds;
    rfds.fd = 0;           //希望内核帮我们关注0号文件描述符上的【事件】
    //如果rfds.events |= POLLIN就一直返回有事件,不清楚为啥?    
    rfds.events = POLLIN; //希望内核关注0号文件描述符上的【读事件】
    rfds.revents = 0;      //这个参数用于内核通知我们有事件就绪了,让我们赶紧来取
    while (1)
    {
        int n = poll(&rfds, 1, -1); // 阻塞等待
        // int n=poll(&rfds,1,0);//非阻塞轮询
        // int n=poll(&rfds,1,1000);//每隔一秒看一眼
        std::cout << "ret : "<<n << std::endl; // 返回值的理解
        switch (n)
        {
        case 0:
            std::cout << "time out..." << std::endl;
            break;

        case -1:
            std::cout << "poll error" << std::endl;
            break;

        default:
            if (rfds.revents & POLLIN)
            {
                std::cout <<"有事件来了 "<< "fd is: "<< rfds.fd << ":"<< "事件已经就绪" << std::endl;
                char buffer[128];
                ssize_t s = read(rfds.fd, buffer, sizeof(buffer) - 1);
                if (s > 0)
                {
                    buffer[s] = 0;
                    std::cout << "recv msg: " << buffer << std::endl;
                }
            }
            break;
        }
    }

    return 0;
}

5)client测试源码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
#define MAXLINE 80
#define SERV_PORT 8080

int main(int argc, char* argv[]){
   struct sockaddr_in servaddr;
   char buf[MAXLINE];
   int sockfd, n;
   char *str;
   if (argc !=2){
       fputs("usage: ./client messsage\n", stderr);
       exit(1);
   }
   str = argv[1];
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
   bzero(&servaddr, sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
   servaddr.sin_port = htons(SERV_PORT);
 
   connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
   write(sockfd, str, strlen(str));
 
   n = read(sockfd, buf, MAXLINE);
   printf("Response from server:\n");
   write(STDOUT_FILENO, buf, n);
 
   close(sockfd);
   return 0;
}

你可能感兴趣的:(嵌入式硬件,物联网)