套接字的阻塞与非阻塞

套接字的默认状态是阻塞。阻塞的套接字调用可分为四种

(1),输入操作,包括read,readv,recv,recvfrom,recvmsg。

阻塞:

TCP:如果接收缓冲区没有数据读,则阻塞,直到数据到达。

UDP:如果接收缓冲区没有数据读,则阻塞,直到UDP数据报到达。

非阻塞:如果输入操作不能被满足(对于TCP套接字即至少有一个字节的数据可读,对于UDP套接字即有一个完整的数据报可读),相应调用将立即返回EWOULDBLOCK。

(2),输出操作,包括write,writev,send,sendto,sendmsg

阻塞:

TCP:如果发送缓冲区没有空间,则阻塞。有一些空间时,则返回不足计数

 

非阻塞:TCP:如果发送缓冲区没有空间,会立即返回一个EWOULDBLOCK错误。如

果有一些空间,返回值将是内核能够复制到该缓冲区中的字节数。这个

字节数也称为不足计数

输出操作对于UDP:没有发送缓冲区,不会因与TCP套接字一样的原因而阻塞,不过有可能会因其他原因而阻塞。

 

(3)接收外来连接,即用于accept函数

阻塞:阻塞在accept,直到有新的连接

非阻塞:没有新的连接来时,accept调用将立即返回一个EWOULDBLOCK

 

(4),发起外出连接,即用于TCP的connect函数。

阻塞:connect函数一直要等到客户收到对于自己的SYN的ACK为止才返回。所以TCP的每一个connect总会阻塞其调用的进程至少一个到服务器的RTT时间。

非阻塞:调用connect,并连接不能立即建立,那么连接的建立能照样发起,不过会返回一个EINPROGRESS错误。这个错误不同于上述三个情形,但客户端和服务端在同一主机,这些连接会立即建立。所以也要预备connect成功返回的情况。

	STATUS connectWithTimeout(int sock, struct sockaddr*addrs, int adrsLen,struct timeval* tmOut)
	{
		int err = 0;
		int len = sizeof(int);
		int flag;
		int ret;
		fd_set set;
		struct timeval mytm;
		memset(&mytm, 0, sizeof(struct timeval));
		if(tmOut!=NULL){
			memcpy(&mytm, tmOut, sizeof(struct timeval));
		}
		flag = 1;
		ioctl(sock,FIONBIO,&flag);
		ret = connect(sock, addrs, adrsLen);//在非阻塞模式下 connect会返回1,下面的操作可以判断
		connect是联通的,若可写则证明socket链接是成功的
		if ( ret == -1 )
		{
			if ( EINPROGRESS == errno )
			{
				FD_ZERO(&set);
				FD_SET(sock,&set);
				if ( select(sock+1,NULL,&set,NULL,tmOut) > 0 )
				{
					getsockopt(sock,SOL_SOCKET,SO_ERROR,&err,(socklen_t*)&len);
					if ( 0 == err )
						ret = OK;
					else
						ret = ERROR;
				}
				else
				{
					ret = ERROR;
				}
			}
		}
		flag = 0;
		ioctl(sock,FIONBIO,&flag);
		if(tmOut!=NULL)
		{
			memcpy(tmOut, &mytm, sizeof(struct timeval));
		}
		return ret;
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值