分类: 嵌入式
2011-08-22 13:02:33
通常情况下套接口是阻塞的,这意味着当一个套接字函数调用不能立即完成时,进程进入睡眠,知道操作完成。可能阻塞套接口的调用分为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在同一台电脑上时,连接可以马上建立。一般情况下需要注册通知事件:
简单讲,非阻塞socket一般与select模型一起使用。