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()返回的连接套接字是否也是阻塞的?相关推荐

  1. aix oracle监听配置_Oracle数据库03用户权限与数据库的连接

    Oracle数据库03-用户权限与数据库的连接 一.oracle用户与权限管理 1.用户管理 只有合法的用户账号才能访问Oracle数据库,Oracle有几个默认的数据库用户. 创建用户核对清单: · ...

  2. 监听当点击微信等app的返回按钮或者浏览器的上一页或后退按钮的事件

    在实际的应用中,我们常常需要实现在移动app和浏览器中点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面或执行一些其它操作的 需求,那在代码中怎样监听当点击微信.支付宝.百度糯米.百度钱包 ...

  3. epoll监听文件_怎么理解把标准输入以ET模式加入epoll,监听EPOLLOUT事件时,epoll_wait多次返回?...

    确实是后面的printf导致的,去掉后面的printf,增加计数器的判断, 可确认epoll_wait只返回了一次.但是为什么printf会影响到标准输入stdin?还是不理解. 修改后符合预期代码如 ...

  4. linux epoll监听套接字实例

    linux epoll机制用于IO多路复用,能够同时监听多个接字,使用起来比较简单. 相关接口: #include <sys/epoll.h>int epoll_create(int si ...

  5. 监听套接字 连接套接字的区别

    摘要:对于服务器编程中最重要的一步等待并接受客户的连接,那么这一步在编程中如何完成,accept函数就是完成这一步的.它从内核中取出已经建立的客户连接,然后把这个已经建立的连接返回给用户程序,此时用户 ...

  6. C语言非阻塞监听按键

    使用scanf()和getchar()处理输入文字很合适,它会停止后续代码执行等待用户输入,直到按回车才继续执行,这种缓冲方式称为阻塞式监听,很多时候我们利用在代码末尾添加getchar()来防止程序 ...

  7. python套接字编程_Python套接字编程(1)——socket模块与套接字编程

    在Python网络编程系列,我们主要学习以下内容: 5. 常见的Python异步编程框架 6. 协程在Python网络编程中的使用 本文介绍Python下的基本套接字编程,主要基于 socket 模块 ...

  8. 如何多个进程监听同一个端口

    1. 问题描述 一个进程监听端口,经验告诉我们,如果多次启动一个进程会报错:"Address already in use!".这是由于bind函数导致的,由于该端口号已经被第一个 ...

  9. 在linux中查看nginx端口监听,Nginx端口监听(listen指令)

    本节主要来介绍 Nginx 中与端口监听有关的配置指令,下表为端口监听指令及其相关说明. 名称 端口监听指令 指令 listen 作用域 server 默认值 listen*:80 或 *:8000 ...

  10. linux listen监听,Linux网络协议栈 -- socket listen监听

    一.sys_listen 对面向连接的协议,在调用 bind(2)后,进一步调用 listen(2),让套接字进入监听状态: int listen(int sockfd, int backlog); ...

最新文章

  1. Jsoup介绍||​​​​​​​jsoup解析url || Jsoup解析字符串||​​​​​​​Jsoup解析文件
  2. 杂七杂八(1)——如何查看本机的.NET Framework版本
  3. UltraVNC反向连接方式的使用
  4. java对五排六列考生随机排座,Java入门第三季6-5扩展练习-随机字符串排序
  5. rest服务swagger_使用Swagger轻松记录您的Play Framework REST API
  6. vue设置多选框默认勾选_Vue实现全选和反选即Vue复选框增加全选功能
  7. HDU 5691 ——Sitting in Line——————【状压动规】
  8. UI自动化测试POM设计之-maven工程
  9. java中怎么声明常量_如何在Java中声明一个常量
  10. kafka 拉取的数据排序_Kafka 源码解析之 Consumer Poll 模型(七)
  11. ryu实例---Hub
  12. 数据预处理和特征工程1--无量纲化:数据归一化、标准化
  13. Java规则引擎easy rules
  14. Python爬虫项目整理
  15. easyx的使用(2)
  16. PHP时间戳和日期的相互转换
  17. 如何解决eclipse黑底白字快速需求
  18. 【OpenCV C++ 案例实战一】实现双人篮球游戏
  19. YOLO系列文章汇总
  20. Bootstrap V3.3.4 组件

热门文章

  1. VC++实现标准型计算器步骤及源码
  2. linux下无法创建组
  3. 羊坊店不眠夜(续集)
  4. 会装64位solaris jdk1.6吗?
  5. leetcode Candy
  6. linux下如何在线添加和移除scsi磁盘?
  7. 如何用iframe代码显示调用网页的指定部分
  8. Discuz!NT3.0博客扩展
  9. CFile, read, write,typeBinary
  10. 7.软件架构设计:大型网站技术架构与业务架构融合之道 --- 框架、软件与中间件