• 非阻塞之connect()


    非阻塞的socket客户端connect()困扰了一下午。因为是非阻塞,不管是否连接上都直接返回,所以就无法知道什么时候连接上。
    一开始想到网上找资料,可惜不多。于是MSDN,总算找到一句话。
    With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, this function will return SOCKET_ERROR and WSAGetLastError will resturn WSAEWOULDBLOCK. The following list shows the three scenarios that are possible in this case:
    Use the select function to determine the completion of the connection request by checking to see if the socket is writeable.
    If the application is using WSAEventSelect to indicate interest in connection events, then the associated event object will be signaled indicating that the connect operation is complete (successfully or not).
    非阻塞socket连接请求不会立即完成。此时,函数返回SOCKET_ERROR且WSAGetLastERROR()返回WSAEWOULDBLOCK。下面展示了此情况的2种场景:
    1、使用select函数检查这个socket是否可写确定连接请求是否完成;
    2、如果程序使用WSAEventSelect表明关注连接事件,那么被关联的事件对象将被置信号表示连接操作完成(成功或失败)
    小代码如下:

    client.c

         FD_ZERO(&wtfds);
    	_timout.tv_sec = 3;
    	_timout.tv_usec = 0;
    
    	msock = socket(AF_INET, SOCK_STREAM, 0);
    	toAddr.sin_family = AF_INET;
    	toAddr.sin_port = htons(7000);
    	toAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.87");
    	
    	if (ioctlsocket(msock, FIONBIO, &iTemp) < 0)
    	{
    		perror("ioctlsocket error\n");
    	}
    	FD_SET(msock, &wtfds);
    
    	iRet = connect(msock, (SOCKADDR*)&toAddr, sizeof(toAddr));
    	if (!iRet)
    	{
    		printf("connect immediately\n");
    		char sndMsg[100] = {0};
    		sprintf(sndMsg, "hello world");
    		if (SOCKET_ERROR == send(msock, sndMsg, strlen(sndMsg), 0))
    		{
    			perror("send error");
    			return 1;
    		}
    		printf("send success\n");
    	}
    	else if (iRet<0 && WSAGetLastError()==WSAEWOULDBLOCK)
    	{
    		int iRet1 = select(0, NULL, &wtfds, NULL, &_timout);
    		if (iRet1 < 0)
    		{
    			perror("connect error\n");
    			return 1;
    		}
    		else if (!iRet1)
    		{
    			perror("timeout error\n");
    			return 1;
    		}
    		else
    		{
    			if (FD_ISSET(msock, &wtfds))
    			{
    				printf("connect success\n");
    				char sndMsg[100] = {0};
    				sprintf(sndMsg, "hello world");
    				if (SOCKET_ERROR == send(msock, sndMsg, strlen(sndMsg), 0))
    				{
    					perror("send error");
    					return 1;
    				}
    				printf("send success\n");
    			}
    		}
    	}
    

    server.c

         msock = socket(AF_INET, SOCK_STREAM, 0);
    	ioctlsocket(msock, FIONBIO, (unsigned long*)&iNonbk);
    	FD_SET(msock, &rdfds);
    	
    	cltAddr.sin_family = AF_INET;
    	cltAddr.sin_port = htons(7000);
    	cltAddr.sin_addr.S_un.S_addr = INADDR_ANY;
    	if (SOCKET_ERROR == bind(msock, (SOCKADDR*)&cltAddr, sizeof(cltAddr)))
    	{
    		perror("bind error");
    		return 1;
    	}
    	if (SOCKET_ERROR == listen(msock, 5))
    	{
    		perror("listen error");
    		return 1;
    	}
    	
    	_tim =  time(NULL);
    	ltime = localtime(&_tim);
    	printf("%d:%d:%d\n", ltime->tm_hour, ltime->tm_min, ltime->tm_sec);
    	
    	iRet = select(0, &rdfds, NULL, NULL, &_timval);
    	if (iRet < 0)
    	{
    		perror("accept error");
    		return 1;
    	}
    	else if(iRet == 0)
    	{
    		perror("timeout error");
    		return 1;
    	}
    	else
    	{
    		if (FD_ISSET(msock, &rdfds))
    			printf("msock is in rdfds\n");
    		else
    			return 1;
    		
    		SOCKET clsock = accept(msock, (SOCKADDR*)&cltAddr, &iLen);
    		if (clsock == INVALID_SOCKET)
    		{
    			printf("clsock is not a valid socket\n");
    			return 1;
    		}
    		if (FD_ISSET(clsock, &rdfds))
    			printf("clsock is in rdfds\n");
    		else
    			printf("clsock is not in rdfds\n");
    		_tim =  time(NULL);
    		ltime = localtime(&_tim);
    		printf("%d:%d:%d\n", ltime->tm_hour, ltime->tm_min, ltime->tm_sec);
    		char recvMsg[100] = {0};
    		int iSize = recv(clsock, recvMsg, 100, 0);
    		printf("from client %s:%s,%d\n", inet_ntoa(cltAddr.sin_addr),recvMsg,WSAGetLastError());
    	}
    
    
  • 相关阅读:
    清北学堂2019NOIP提高储备营DAY1
    最小生成树--克鲁斯卡尔算法(Kruskal)
    关于队列(还有广度优先搜索的例题)
    染色问题
    行列式的相关知识
    素数筛法
    中国剩余定理(孙子定理)
    AOJ 9.University
    AOJ 8.童年生活二三事
    AOJ 7.Redraiment猜想
  • 原文地址:https://www.cnblogs.com/littlejohnny/p/1919434.html
Copyright © 2020-2023  润新知