Linux poll详解(3)
导读:Linux,编译上述程序生成 poll_server 并运行,然后使用 nc 命令模拟三个客户端并给 poll_server 发送消息,效果如下: 由于 nc 命令是以 \n 作为结束标志的,
Linux
编译上述程序生成 poll_server 并运行,然后使用 nc 命令模拟三个客户端并给 poll_server 发送消息,效果如下:

由于 nc 命令是以\n作为结束标志的,所以poll_server收到客户端消息时显示时分两行的。
通过上面的示例代码,我们也能看出poll函数存在的一些缺点:
- 在调用poll函数时,不管有没有有意义,大量的 fd 的数组被整体在用户态和内核地址空间之间复制;
- 与 select 函数一样,poll 函数返回后,需要遍历 fd 集合来获取就绪的 fd,这样会使性能下降;
- 同时连接的大量客户端在一时刻可能只有很少的就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。
与 select 函数实现非阻塞的 connect 原理一样,我们可以使用 poll 去实现,即通过 poll 检测 clientfd 在一定时间内是否可写,示例代码如下:
/**
* Linux 下使用poll实现异步的connect,linux_nonblocking_connect_poll.cpp
* zhangyl 2019.03.16
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <poll.h>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 3000
#define SEND_DATA "helloworld"
int main(int argc, char* argv[])
{
//1.创建一个socket
int clientfd = socket(AF_INET, SOCK_STREAM, 0);
if (clientfd == -1)
{
std::cout << "create client socket error." << std::endl;
return -1;
}
//将 clientfd 设置成非阻塞模式
int oldSocketFlag = fcntl(clientfd, F_GETFL, 0);
int newSocketFlag = oldSocketFlag | O_NONBLOCK;
if (fcntl(clientfd, F_SETFL, newSocketFlag) == -1)
{
close(clientfd);
std::cout << "set socket to nonblock error." << std::endl;
return -1;
}
//2.连接服务器
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
serveraddr.sin_port = htons(SERVER_PORT);
for (;;)
{
int ret = connect(clientfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (ret == 0)
{
std::cout << "connect to server successfully." << std::endl;
close(clientfd);
return 0;
}
else if (ret == -1)
{
if (errno == EINTR)
{
//connect 动作被信号中断,重试connect
std::cout << "connecting interruptted by signal, try again." << std::endl;
continue;
} else if (errno == EINPROGRESS)
{
//连接正在尝试中
break;
} else {
//真的出错了,
close(clientfd);
return -1;
}
}
}
pollfd event;
event.fd = clientfd;
event.events = POLLOUT;
int timeout = 3000;
if (poll(&event, 1, timeout) != 1)
{
close(clientfd);
std::cout << "[poll] connect to server error." << std::endl;
return -1;
}
if (!(event.revents & POLLOUT))
{
close(clientfd);
std::cout << "[POLLOUT] connect to server error." << std::endl;
return -1;
}
int err;
socklen_t len = static_cast<socklen_t>(sizeof err);
if (::getsockopt(clientfd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
return -1;
if (err == 0)
std::cout << "connect to server successfully." << std::endl;
else
std::cout << "connect to server error." << std::endl;
//5. 关闭socket
close(clientfd);
return 0;
}
运行效果与前面的 select 实现非阻塞的 connect 一样,这里就不再给出运行效果图了。
上述就是Linux 和 poll详解的详细讲解,IT袋网小编希望本文能给你带来生活上的帮助!
相关阅读
-
win10旗舰版一键还原步骤 关于win10系统备份及还原方法
为大家分享win10旗舰版一键还原步骤和关于win10系统备份及还原方法的电脑小知识,一定能解决您的问题的,一起来了解吧! 在备份后担心别人对现在的系统进行随意还原而导致系统文件丢失等
-
win10电脑输入法打字不显示选字框 电脑没有输入法调不出来的原因
今天小编介绍win10电脑输入法打字不显示选字框方面的介绍,下面小编为您详细解答 有的小伙伴可能会遇到以下这样的问题: 中文模式没有选词框示例图 明明已经切换到中文模式了,但是打出
-
优麒麟安装方法详细介绍 优麒麟怎么安装windows系统
一个电脑小知识,为大家介绍优麒麟安装方法详细介绍的教程内容,关于优麒麟安装方法详细介绍 优麒麟怎么安装windows系统,接下来一起来看看吧。 优麒麟是一款非常不错的Linux系统,不过相
-
win7连不上网络怎么办 win7无法连接网络怎么办
相对于大多数人win7无法连接网络怎么办方面的内容,关于win7连不上网络怎么办 win7无法连接网络怎么办,下面小编为您详细解答 今天小编要为大家带来的就是如何解决win7无法连接网络怎么办


