监听套接字是非阻塞的,accept()返回的连接套接字是否也是阻塞的?
以muduo为
例,在类Acceptor
中,成员变量监听套接字acceptSocket_
在Acceptor构造时调用socket::createNonblockingOrDie()
, 它的实现如下:
int sockets::createNonblockingOrDie(sa_family_t family)
{#if VALGRINDint sockfd = ::socket(family, SOCK_STREAM, IPPROTO_TCP);if (sockfd < 0){LOG_SYSFATAL << "sockets::createNonblockingOrDie";}setNonBlockAndCloseOnExec(sockfd);
#elseint sockfd = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if (sockfd < 0){LOG_SYSFATAL << "sockets::createNonblockingOrDie";}
#endifreturn sockfd;
}
其中又调用了setNonBlockAndCloseOnExec()
,注意其中设置套接字的方法,先通过fcntl()获取原属性,然后原属性 | 上O_NONBLOCK,再通过fcntl()设置修改后的新属性。
#if VALGRIND || defined (NO_ACCEPT4)
void setNonBlockAndCloseOnExec(int sockfd)
{// non-blockint flags = ::fcntl(sockfd, F_GETFL, 0);flags |= O_NONBLOCK;int ret = ::fcntl(sockfd, F_SETFL, flags);// FIXME check// close-on-execflags = ::fcntl(sockfd, F_GETFD, 0);flags |= FD_CLOEXEC;ret = ::fcntl(sockfd, F_SETFD, flags);// FIXME check(void)ret;
}
#endif} // namespace
监听套接字就被设置成了非阻塞。
当有新的连接请求到来时,套接字可读,触发调用Acceptor::handleRead()
,其实现如下:
void Acceptor::handleRead()
{loop_->assertInLoopThread();InetAddress peerAddr;//FIXME loop until no moreint connfd = acceptSocket_.accept(&peerAddr);if (connfd >= 0){// string hostport = peerAddr.toIpPort();// LOG_TRACE << "Accepts of " << hostport;if (newConnectionCallback_){newConnectionCallback_(connfd, peerAddr);}else{sockets::close(connfd);}}else{LOG_SYSERR << "in Acceptor::handleRead";// Read the section named "The special problem of// accept()ing when you can't" in libev's doc.// By Marc Lehmann, author of libev.if (errno == EMFILE){::close(idleFd_);idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL);::close(idleFd_);idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);}}
}
其中又调用了sockets::accept(int sockfd, struct sockaddr_in6* addr)
,其实现如下:
int sockets::accept(int sockfd, struct sockaddr_in6* addr)
{socklen_t addrlen = static_cast<socklen_t>(sizeof *addr);
#if VALGRIND || defined (NO_ACCEPT4)int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen);setNonBlockAndCloseOnExec(connfd);
#elseint connfd = ::accept4(sockfd, sockaddr_cast(addr),&addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
#endifif (connfd < 0){int savedErrno = errno;LOG_SYSERR << "Socket::accept";switch (savedErrno){case EAGAIN:case ECONNABORTED:case EINTR:case EPROTO: // ???case EPERM:case EMFILE: // per-process lmit of open file desctiptor ???// expected errorserrno = savedErrno;break;case EBADF:case EFAULT:case EINVAL:case ENFILE:case ENOBUFS:case ENOMEM:case ENOTSOCK:case EOPNOTSUPP:// unexpected errorsLOG_FATAL << "unexpected error of ::accept " << savedErrno;break;default:LOG_FATAL << "unknown error of ::accept " << savedErrno;break;}}return connfd;
}
从其实现来看,监听套接字为非阻塞时,对其调用accept()
返回的套接字应该还是为阻塞的,不然也不会接着调用setNonBlockAndCloseOnExec()
。如果要使accept()
返回的套接字直接就是非阻塞的,可以调用accept4()
[如果支持的话],它比accept()
多了一个参数[SOCK_NONBLOCK | SOCK_CLOEXEC],可以通过设置该参数使返回的连接套接字直接就是非阻塞的。
监听套接字是非阻塞的,accept()返回的连接套接字是否也是阻塞的?相关推荐
- aix oracle监听配置_Oracle数据库03用户权限与数据库的连接
Oracle数据库03-用户权限与数据库的连接 一.oracle用户与权限管理 1.用户管理 只有合法的用户账号才能访问Oracle数据库,Oracle有几个默认的数据库用户. 创建用户核对清单: · ...
- 监听当点击微信等app的返回按钮或者浏览器的上一页或后退按钮的事件
在实际的应用中,我们常常需要实现在移动app和浏览器中点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面或执行一些其它操作的 需求,那在代码中怎样监听当点击微信.支付宝.百度糯米.百度钱包 ...
- epoll监听文件_怎么理解把标准输入以ET模式加入epoll,监听EPOLLOUT事件时,epoll_wait多次返回?...
确实是后面的printf导致的,去掉后面的printf,增加计数器的判断, 可确认epoll_wait只返回了一次.但是为什么printf会影响到标准输入stdin?还是不理解. 修改后符合预期代码如 ...
- linux epoll监听套接字实例
linux epoll机制用于IO多路复用,能够同时监听多个接字,使用起来比较简单. 相关接口: #include <sys/epoll.h>int epoll_create(int si ...
- 监听套接字 连接套接字的区别
摘要:对于服务器编程中最重要的一步等待并接受客户的连接,那么这一步在编程中如何完成,accept函数就是完成这一步的.它从内核中取出已经建立的客户连接,然后把这个已经建立的连接返回给用户程序,此时用户 ...
- C语言非阻塞监听按键
使用scanf()和getchar()处理输入文字很合适,它会停止后续代码执行等待用户输入,直到按回车才继续执行,这种缓冲方式称为阻塞式监听,很多时候我们利用在代码末尾添加getchar()来防止程序 ...
- python套接字编程_Python套接字编程(1)——socket模块与套接字编程
在Python网络编程系列,我们主要学习以下内容: 5. 常见的Python异步编程框架 6. 协程在Python网络编程中的使用 本文介绍Python下的基本套接字编程,主要基于 socket 模块 ...
- 如何多个进程监听同一个端口
1. 问题描述 一个进程监听端口,经验告诉我们,如果多次启动一个进程会报错:"Address already in use!".这是由于bind函数导致的,由于该端口号已经被第一个 ...
- 在linux中查看nginx端口监听,Nginx端口监听(listen指令)
本节主要来介绍 Nginx 中与端口监听有关的配置指令,下表为端口监听指令及其相关说明. 名称 端口监听指令 指令 listen 作用域 server 默认值 listen*:80 或 *:8000 ...
- linux listen监听,Linux网络协议栈 -- socket listen监听
一.sys_listen 对面向连接的协议,在调用 bind(2)后,进一步调用 listen(2),让套接字进入监听状态: int listen(int sockfd, int backlog); ...
最新文章
- Jsoup介绍||​​​​​​​jsoup解析url || Jsoup解析字符串||​​​​​​​Jsoup解析文件
- 杂七杂八(1)——如何查看本机的.NET Framework版本
- UltraVNC反向连接方式的使用
- java对五排六列考生随机排座,Java入门第三季6-5扩展练习-随机字符串排序
- rest服务swagger_使用Swagger轻松记录您的Play Framework REST API
- vue设置多选框默认勾选_Vue实现全选和反选即Vue复选框增加全选功能
- HDU 5691 ——Sitting in Line——————【状压动规】
- UI自动化测试POM设计之-maven工程
- java中怎么声明常量_如何在Java中声明一个常量
- kafka 拉取的数据排序_Kafka 源码解析之 Consumer Poll 模型(七)
- ryu实例---Hub
- 数据预处理和特征工程1--无量纲化:数据归一化、标准化
- Java规则引擎easy rules
- Python爬虫项目整理
- easyx的使用(2)
- PHP时间戳和日期的相互转换
- 如何解决eclipse黑底白字快速需求
- 【OpenCV C++ 案例实战一】实现双人篮球游戏
- YOLO系列文章汇总
- Bootstrap V3.3.4 组件