83-非阻塞 I/O

来源:互联网 发布:linux命令行删除文件 编辑:程序博客网 时间:2024/05/18 20:35

回顾一下上一篇文章,阻塞版本的 writen 固然好用,但是也有风险,我们不能把希望寄托在增加客户端 TCP 发送缓冲区和接收缓冲区的大小上,而是应该采取更加有保障的措施。前面说过,可以使用非阻塞 IO,也可以使用多进程或多线程。

本文,我们先来讨论一下非阻塞 I/O 的特性。

1. 概述

可能产生阻塞的套接字调用分成四类:

1) 输入操作,包括 read, readv, recv, recvfrom, recvmsg.
对于 TCP 和 UDP 而言,如果接收缓冲区为空,调用这些函数就导致进程阻塞。如果套接字是非阻塞的,则返回 -1, 置 errno 为 EWOUDBLOCK.
2) 输出操作,包括 write, writev, send, sendto, sendmsg.
对于 TCP 而言,如果发送缓冲区满了,调用这些函数会导致进程阻塞。UDP 没有发送缓冲区,因此不太可能阻塞(unp 说可能会因为其它原因而阻塞)。如果套接字是非阻塞的,同样返回 -1,errno 置为 EWOULDBLOCK.
3) 接受连接,accept 函数。
如果没有新的连接,调用 accept 会导致进程阻塞。对于非阻塞套接字,返回 -1,errno 置为 EWOULDBLOCK.
4) 发起连接,connect 函数。
对于 TCP 来说,connect 函数要等到到自己的 SYN 的 ACK 收到才会返回。虽然 UDP 也可以使用 connect,但是它的含义等同于 setpeername,所以不会阻塞。
对于非阻塞套接字,如果连接不能立即建立,connect 在发送 SYN 后直接返回了,此时 errno 设置为 EINPROGRESS.

2. 本章学习路线

上一篇文章我们已经回顾了我们写过 N 多次的回射客户端,并探讨了它存在的问题。接下来,将讨论:

  • 非阻塞读写
  • 非阻塞 connect
  • 非阻塞 accept
0 0