• 非阻塞I/O


    通常情况下套接口是阻塞的,这意味着当一个套接字函数调用不能立即完成时,进程进入睡眠,知道操作完成。可能阻塞套接口的调用分为4种。

    1、输入:recv、recvfrom。当阻塞的tcp调用时,如果套接口缓冲区没有数据可读,进程将在数据到达前一直处于睡眠。同样如果一个阻塞的udp缓冲区为空,进程在下一个数据报到来前一直处于睡眠状态

    而非阻塞套接口不管是否有数据都将直接返回,有数据正常返回,没数据时WSAGetLastError()会返回WSAEWOULDBLOCK。

    2、输出:send、sendto。对一个tcp socket,内核从应用程序缓冲区想套接口缓冲区拷贝数据。当套接口没有空间时,进程处于睡眠,知道足够空间(windows xp下套接口的默认发送和接受缓冲区是8K,用getsockopt(m_sock, SOL_SOCKET, SO_RCVBUF,&iSize,&len)取得,也可以用setsockopt()设置缓冲区大小)。

    对于非阻塞tcp套接字,如果套接字缓冲区没有空间,输出返回SOCKET_ERROR,用WSAGetLastError()得到WSAEWOULDBLOCK。直到缓冲区有空间,返回内核向套接字缓冲区拷贝的字节数。

    udp套接口没有发送区,内核只是拷贝进程数据向协议栈的下层传递,加上udp与ip的头部。因此一个阻塞udp的socket的输出操作不会阻塞。

    3、接受外来连接:accept。如果一个阻塞套接口调用accept,而且没有新的连接,进程进入睡眠。在非阻塞接口调用accept,accept立即返回(有点疑义,后面补上)

    4、初始化连接:tcp的connect。(udp的connect并不建立真实连接,只是内核保存了对方ip和端口)tcp的连接建立包括3次握手过程,而且客户端在接收到其SYN的ACK前不会返回。就是说tcp connect至少会阻塞一次往返时间(RTT)。

    而在一个非阻塞的tcp套接口上调用connect,一般不能马上建立连接,返回SOCKET_ERROR,WSAGetLastError()得到WSAEWOULDBLOCK错,但是connect的三次握手继续进行。需要注意的是client与server在同一台电脑上时,连接可以马上建立。一般情况下需要注册通知事件:

    • select检查socket是否可写
    • WSAEventSelect的FD_CONNECT(这个没用过)

    简单讲,非阻塞socket一般与select模型一起使用。

  • 相关阅读:
    1012 The Best Rank (25 分)(排序)
    1011. World Cup Betting (20)(查找元素)
    1009 Product of Polynomials (25 分)(模拟)
    1008 Elevator (20 分)(数学问题)
    1006 Sign In and Sign Out (25 分)(查找元素)
    1005 Spell It Right (20 分)(字符串处理)
    Kafka Connect 出现ERROR Failed to flush WorkerSourceTask{id=local-file-source-0}, timed out while wait
    flume、kafka、avro组成的消息系统
    Java23种设计模式总结【转载】
    Java编程 思维导图
  • 原文地址:https://www.cnblogs.com/littlejohnny/p/1921069.html
Copyright © 2020-2023  润新知