码迷,mamicode.com
首页 > 其他好文 > 详细

UNIX网络编程-非阻塞connect和非阻塞accept

时间:2015-08-17 19:10:49      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

1、非阻塞connect

    在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长的时间,我们在连接之前将socket设置为非阻塞模式之后,调用connect函数之后,立即返回,如果成功返回0,如果不成功则返回EINPROGRESS,这个值表明连接正在进行,我们可以设置一个超时时间,然后在这个时间段内不停的检查socket是否连接上了,如果在这个时间段内还没有连上,则返回失败。在这个检查的过程中我们可以做一些其他事情,而不必等待连接。

实现这个检查过程,有两种方式:一种方法是用一个while循环来做,另一种方法是通过select来做。

方法一:

 1 if (connect(sockfd, (struct sockaddr *) &address, sizeof(address)) < 0)
 2 {
 3     err = errno;
 4 
 5     if (err != EINPROGRESS)
 6     {
 7         socket_ok = -1;
 8     }
 9     else
10     {
11         while (true) /* is noblocking connect, check it until ok or timeout */
12         {
13             connect(sockfd, (struct sockaddr *) &address, sizeof(address));
14 
15             err = errno;
16             switch (err)
17             {
18             case EISCONN:   /* connect ok */
19                 connect_ok = 1;
20                 break;
21 
22             case EALREADY:  /* is connecting, need to check again */
23                 usleep(100);
24                 break;
25 
26             default:
27                 connect_ok = -1;
28                 break;
29             }
30 
31             if (connect_ok == 1)
32             {
33                 break;
34             }
35 
36             if (connect_ok == -1)
37             {
38                 break;
39             }
40 
41             if ( (timeout > 0) && ((time(NULL) - begin_time) > timeout) )
42             {
43                 break;
44             }
45         }
46     }
47 }
48 else  /* Connect successful immediately        */
49 {
50     connect_ok = 1;
51 }

 

方法二:

 1 int CTCPConn::AsynConnectToServer(timeval tmConnTimeout)
 2 {
 3        int nRet = -1;
 4 
 5        if( m_nEntityID <= 0 )
 6        {
 7               return -1;
 8        }
 9 
10        if( m_stSocket.CreateClient() )
11        {
12               LOG("Conn create client of DBServer %d failed.\n", m_nEntityID);
13               return -1;
14        }
15 
16        nRet = m_stSocket.AsynConnectTo(m_ulIPAddr, m_unPort);
17 
18        // 返回-1表示正在连接
19        if ( nRet != -1 )
20        {
21               return nRet;
22        }
23 
24        fd_set writeSets;
25        SOCKET iSocketFD = m_stSocket.GetSocketFD();
26        FD_ZERO(&writeSets);
27        FD_SET(iSocketFD, &writeSets);
28 
29        nRet = select(iSocketFD + 1, NULL, &writeSets, NULL, &tmConnTimeout);
30 
31        if ( nRet <= 0 )
32        {
33               m_stSocket.Close();
34               return -4;
35        }
36 
37        if ( !FD_ISSET(iSocketFD, &writeSets) )
38        {
39               m_stSocket.Close();
40               return -5;
41        }
42 
43 #ifdef WIN32
44        int nLen = sizeof(nRet);
45        getsockopt(iSocketFD, SOL_SOCKET, SO_ERROR, (char*)&nRet, &nLen);
46 #else
47        socklen_t nLen = sizeof(socklen_t);
48        getsockopt(iSocketFD, SOL_SOCKET, SO_ERROR, (char*)&nRet, &nLen);
49 #endif
50 
51        if( nRet != 0 )
52        {
53               m_stSocket.Close();
54               return -6;
55        }
56 
57        m_stSocket.SetConnected();
58        
59        return 0;
60 }

 

用select函数检查是否可写,这里可以设置一个超时时间,如果连接成功了的话,则socket变为可写的,select函数是可以检测到。检测到可写之后,用getsockopt函数来获取选项值,如果为0,则证明连接成功。

非阻塞连接的用途:

(1)可以在socket进行三次握手的时候干其他事情,不至于阻塞;

(2)可以同时进行多个连接,在web应用中比较常见(本人自己认为,浏览器就用到了这个,但具体怎么做的没有去了解)

(3)可以设置较短的超时时间,一般connect设计的时候都会有一个超时时间,会比较长,设置为非阻塞我们就可以自己来设定超时时间。

2、非阻塞accept

非阻塞accept主要用来解决以下问题:

用select检测socket状态,如果有连接就调用accept,这样如果在select检测到由连接请求,在调用accept之前,这个请求断开了,然后调用accept的时候就会阻塞在哪里,除非这时有另外一个连接请求,如果没有,则一直被阻塞在那里。(本人以为如果把accept单独放在一个线程中,不会出现以上问题,就是不明白这样做有什么坏处)。

 

UNIX网络编程-非阻塞connect和非阻塞accept

标签:

原文地址:http://www.cnblogs.com/mhscn/p/4737354.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!