TCP non-blocking settings

 
 

The default state of a socket is blocking, which means that when a socket call that cannot be completed immediately is issued, its process will be put to sleep, waiting for the response operation to complete. Socket calls that may block can be divided into the following Four categories:

(1) Input operations, including read, readv, recv, recvfrom, recvmsg;

(2) Output operations, including write, writev, send, sendto, sendmsg;

(3) Accept external connections, that is, the accept function.

In blocking mode, when there is no new connection, the thread will go to sleep; in non-blocking mode, when there is no new connection, the WOULDBLOCK error is returned immediately.

(4) Initiate an outgoing connection, that is, the connect function of tcp;

In blocking mode, connect returns only when the TCP connection is established successfully or has an error. There are several specific cases, which will not be described here; in non-blocking mode, the function will immediately return an INPROCESS error (select to detect whether the connection is established or not) success

There are several ways to set blocking and non-blocking under linux and windows:

linux:

fcntl(socket, F_SETFL, flags | O_NONBLOCK);

windows:

ioctlsocket(socket,FIONBIO,&iMode);

ioctlsocket,WSAAsyncselect()和WSAEventselect()

 
 
static int tcp_send(SOCKET sockClient,const char* request_head,long slen,bool &iFlag)
{
	
	int iRet = 0;
	int i = 0;
       long already_bytes = 0;
       int lenSend = 0;

	fd_set fd;
	timeval tiout;
	tiout.tv_sec = 1;
	tiout.tv_usec = 0;

	for (i = 0;(i < 3) && (!iFlag); i++)//iFlag exits when bexit, preventing waiting for events in this loop for too long
	{
		FD_ZERO(&fd);
		FD_SET(sockClient, &fd);
		iRet = select(sockClient+1,NULL,&fd,NULL,&tiout);

		if (iRet > 0  && FD_ISSET(sockClient,&fd))
		{
		    lenSend = send(sockClient, request_head+already_bytes, slen-already_bytes, 0);
            if(lenSend == -1)
            {
                continue;	    
            }
           already_bytes += lenSend;
           if(already_bytes == slen)
           {
               return 0;
           }
        }
		else // try 3 times regardless of whether the error timed out or not waited for a while
		{
			continue;
		}
		
	}

	return -1;
}

static int tcp_connect(SOCKET sockClient,char* remote_host,int remote_port ,bool &iFlag)
{	 
	
	int iRet = 0;
	int i = 0;
	string  remote_ip = remote_host;
	struct sockaddr_in	remote_addr;
	remote_addr.sin_family = AF_INET;
	remote_addr.sin_addr.S_un.S_addr = inet_addr(remote_ip.c_str());
	remote_addr.sin_port = htons(remote_port);	 

	
	  // try to connect to the server  
	  iRet = connect(sockClient,(struct sockaddr *)&remote_addr,sizeof(SOCKADDR));
	  if (0 == iRet)  
	  {  
		  return 0 ; // connect successfully  
	  }  
	  else if (iRet < 0 && GetLastError() == 10035) //errno == EINPROGRESS means link is being established
	  {  
		  fd_set fd;
		  timeval tiout;
		  tiout.tv_sec = 1;
		  tiout.tv_usec = 0;
          for (i = 0; (i < 3) && (!iFlag); i++)//iFlag exits when bexit, to prevent waiting too long in this loop
          {
              FD_ZERO(&fd);  
              FD_SET(sockClient, &fd); //The opposite is FD_CLR(sockClient, &fd)

              iRet = select(sockClient+1,NULL,&fd,NULL,&tiout);
              if (iRet <= 0)  
              {  
                  continue; // there is an error (select error or timeout)  
              }  
              //The sockClient read event or write time will be detected, which does not mean that the connect is successful
              if(FD_ISSET(sockClient,&fd))
              {   
                  int error = -1;  
                  int optLen = sizeof(int);  

                  if(getsockopt(sockClient, SOL_SOCKET, SO_ERROR, (char*)&error, &optLen) < 0)
                  {
                      continue; //build failed close(sockClient)
                  }
                  if (0 != error)  
                  {  
                      continue; // there is an error  
                  }  
                  else  
                  {
                      return 0; // no error  
                  }  
              }		 
	      }  
       }
	  else
	  {
		 return -1;;//Error occurred
	  }
	return -1;
}

static int tcp_receive(SOCKET sockClient, char *pOut,int len ,bool &iFlag)
{
	int iRet = 0;
	int i = 0;
	
	fd_set fd;
	timeval tiout;
	tiout.tv_sec = 1;
	tiout.tv_usec = 0;

	for (i = 0; (i < 3) && (!iFlag); i++)//iFlag exits when bexit, to prevent waiting for events in this loop for too long
	{
		FD_ZERO(&fd);
		FD_SET(sockClient, &fd);
		iRet = select(sockClient+1,&fd,NULL,NULL,&tiout);
		
		if (iRet > 0  && FD_ISSET(sockClient,&fd))
		{
			return recv(sockClient, pOut, len, 0);
		}
		else // try 3 times regardless of whether the error timed out or not waited for a while
		{
			continue;
		}
		
	}
	
	return -1;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325473212&siteId=291194637