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;
}
2)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;
}