Here is what MSDN says:

http://msdn.microsoft.com/en-us/library/ms737625%28VS.85%29.aspx

With a nonblocking socket, the connection attempt cannot be completed
immediately. In this case, *connect* will return SOCKET_ERROR, and *
WSAGetLastError* will return
WSAEWOULDBLOCK<http://msdn.microsoft.com/en-us/library/ms740668%28VS.85%29.aspx#winsock.wsaewouldblock_2>.
In this case, there are three possible scenarios:

   - Use the 
*select*<http://msdn.microsoft.com/en-us/library/ms740141%28VS.85%29.aspx>function
to determine the completion of the connection request by checking
   to see if the socket is writeable.


And here is what man connect says on UNIX:

 *EINPROGRESS*
             The socket is non-blocking and the  connection  cannot
be  completed  immediately.   It  is  possible  to
             select(2) <http://man-wiki.net/index.php/2:select>  or
poll(2) <http://man-wiki.net/index.php/2:poll>  for  completion  by
selecting  the  socket for writing. After select(2)
<http://man-wiki.net/index.php/2:select> indicates
             writability, use getsockopt(2)
<http://man-wiki.net/index.php/2:getsockopt> to read the *SO_ERROR*
option at level *SOL_SOCKET* to determine  whether  *con-*
             *nect*()  completed  successfully  (*SO_ERROR*  is zero)
or unsuccessfully (*SO_ERROR* is one of the usual error
             codes listed here, explaining the reason for the failure).


So it seems that after select I need to check for writability, which is what
I have been doing.


Just as a test I started checking for read/write/error events by changing my
code to this:

                  fd_set myrset;
                  FD_ZERO(&myrset);
                  FD_SET(m_sock_fd, &myrset);
                  fd_set mywset;
                  FD_ZERO(&mywset);
                  FD_SET(m_sock_fd, &mywset);
                  fd_set myeset;
                  FD_ZERO(&myeset);
                  FD_SET(m_sock_fd, &myeset);
                  status = select(m_sock_fd+1, &myrset, &mywset, &myeset,
&tv);
                      if (FD_ISSET(m_sock_fd,&myrset))
                      {
                          cout << "read set" << endl << flush;
                      }
                      if (FD_ISSET(m_sock_fd,&mywset))
                      {
                          cout << "write set" << endl << flush;
                      }
                      if (FD_ISSET(m_sock_fd,&myeset))
                      {
                          cout << "error set" << endl << flush;
                      }

To my surprise, Windows puts the socket in the error set!!! which to my
knowledge is not documented.

Once select returns after signaling the error set, I call this:

 getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon)

Now valopt is set to WSAECONNREFUSED.


On the UNIX side, you are right, the connect returns EINPROGRESS, then the
select signals the write set [ as documented ], the getsockopt then gives me
ECONNREFUSED.

I think this is a bug on Windows or at least the documentation is wrong. It
should say to check on the error set not on the write set using the select
call...


Thanks. I have solved my problem.

On Sun, Aug 23, 2009 at 6:20 PM, Ger Hobbelt <g...@hobbelt.com> wrote:

> Probably the difference is due to timing; to get the connection
> refused response, the client needs to at least transmit a packet and
> either never see a response (timing out) or receive a RST or (in some
> cases) an ICMP host-unreachable packet. Any way, the minimum time
> required to give you the 'connection refused' response is two network
> travels at the absolute minimum. Which means: it takes time.
>
> 'nonblocking' simply means 'I don't want to wait', so theoretically
> the IP stack doesn't have to wait even a milli/micro/femtosecond
> before returning to you. Which is what winsock does: queue request,
> instant return, hence wouldblock. Apparently (and this can be due to a
> myriad of reasons) your UNIX box either already 'knows' the server is
> down or has an IP stack which waits a short while before returning
> from connect, even in nonblocking conditions, so it is able to deliver
> a 'connection refused' to you on the initial return.
>
> > It is true that by using a nonblocking connect I want an instant answer
> but
> > most importantly I want a correct answer.
>
> The answer is correct, because the answer is depending on time.
> This may sound weird to you as it looks like the whole time/async
> behaviour pattern here are what's troubling you, but the nonblocking
> means the 'wouldblock' behaviour is the behaviour you would /expect/
> from the system; the fact that the other machine isn't doing this is,
> at best, something to frown and ponder. /That/ one worries me, not the
> Win box.
> How can that machine know /instantaneously/ that the server at other
> end of the wire is down? There's no paranormal vibe there, so... is
> it's IP stack implemented to wait /anyway/ (bad!), despite the fact
> that it knows it's got a nonblocking request from the application? Is
> it at all /aware/ that this is a nonblocking handle/request here?! Or
> more obscure and less probable: Is it caching icmp or other previous
> responses regarding availability of other machines and shortcircuiting
> the request due to that cached info? etc. (Or is the unix box the
> server and client both, i.e. connection to localhost or eqv., so the
> IP stack can short-circuit the request that way?)
>
> Your issue is, IMO, not the wouldblock, but the connrefused, which is
> unexpected for a truely nonblocking socket. I checked my specs, and I
> was correct in saying that you need to check for a READ event in
> select() to get a notification about a completed nonblocking connect,
> both on UNIX and WinSock. While you don't do that (you only ask
> select() about WRITE events there) the select() will sit an pick it's
> nose until timeout.
>
> Again, nonblocking is you telling the kernel 'go fetch, while I do
> other stuff at the same time' and the /direct/ return of connrefused
> only means one thing: the bastard is forcing you to wait anyhow until
> the system/kernel is done doing its thing, which is /precisely/ what
> you said, through NONblocking, you do NOT want (the waiting on the
> call to finish). Either that or the unix box has obtained
> precognition, which is a bit worrysome in its own way.
>
>
> PS: are you addressing the server by IP number or domain name? In the
> latter case, have you made sure the DNS request which converts the
> FQDN to an IP produced a positive result? In other words: is connect
> being fed a usable IP number and ditto port on both boxes? Are those
> numbers identical on both boxes? Just making sure here as the
> immediate connection refused is suspect.
>
>
>
> On Sun, Aug 23, 2009 at 5:35 PM, Md Lazreg<mdlaz...@gmail.com> wrote:
> > Thank you Ger for your reply.
> >
> >
> > It is true that by using a nonblocking connect I want an instant answer
> but
> > most importantly I want a correct answer.
> >
> > Using the same code under UNIX I get two instant correct answers:
> >
> > ECONNREFUSED   [If my SSL server is down]
> > EINPROGRESS       [If my SSL server is up and listening]
> >
> >
> > But under Windows I get the same answer regardless of the state of my SSL
> > server:
> >
> > WSAEWOULDBLOCK
> >
> > My question is why _using the same code_ Windows is returning
> WSAEWOULDBLOCK
> > instead of WSAECONNREFUSED when my server is down? while UNIX correctly
> > returns ECONNREFUSED...
> >
> > Thanks
> >
> >
> >
> >
> > On Sun, Aug 23, 2009 at 5:04 PM, Ger Hobbelt <g...@hobbelt.com> wrote:
> >>
> >> Since you use a nonblocking connect, you're essentially telling the
> >> software you want instant return. Which is what you get.
> >>
> >> Given that a TCP connection takes a little time (three network travels
> >> at least), that's definitely more time than you wish to wait given
> >> your nonblocking intent, so the IP stack properly and correctly tells
> >> you it'll take some time before you get the final result -->
> >> wouldblock.
> >>
> >> The next bit is where I'm a bit rusty (read as: the peculiarities of
> >> WinSock have eroded in my brain), but a glance at the code shows
> >> you're only select()ing for writing and IIRC a finalized non-blocking
> >> connect is equivalent to a 'ready-for-READING' select signal - for
> >> which you are not listening in your select as that argument is NULL.
> >> Hence my advise to also pass your handle in a separate fdset to
> >> select(read), i.e
> >>
> >>                status = select(m_sock_fd+1, &myreadset, &mywriteset,
> >> NULL, &tv);
> >>
> >> (so you can tell upon return which one fired)
> >>
> >>
> >> and lastly there's the ever-there mind-you nitpick that nonblocking
> >> I/O is well served with a statemachine around it, i.e. a loop, which
> >> tracks the current state of your connections/activity and acts upon
> >> that - it's the long way of saying that a connection may take longer
> >> than 20 seconds to establish, so an if-chain and a long wait isn't the
> >> end-all there, but this nitpick is not your problem. Yet. And the code
> >> structure is not enough to prove there's no statemachine already there
> >> in your code; the current code layout is a (very) weak hint, 's all.
> >>
> >>
> >> Anyway, a tip: this is generic TCP/IP socket programming we're talking
> >> about here and do yourself a favor and get a hold of the books by W
> >> Richard Stevens (R.I.P.). It's what I grew up with and those books of
> >> his have been among the very few which have never let me down in the
> >> hour of need.  They're still 100% applicable and for IPv6 specifics,
> >> there's little enough change that the internet and manpages suffice
> >> for that. They are not WinSock specific, but for that one's
> >> peculiarities (such as the WSASelect limits) there's MSDN.
> >>
> >> Take care,
> >>
> >> Ger
> >>
> >
> >
>
>
>
> --
> Met vriendelijke groeten / Best regards,
>
> Ger Hobbelt
>
> --------------------------------------------------
> web:    http://www.hobbelt.com/
>        http://www.hebbut.net/
> mail:   g...@hobbelt.com
> mobile: +31-6-11 120 978
> --------------------------------------------------
> ______________________________________________________________________
> OpenSSL Project                                 http://www.openssl.org
> User Support Mailing List                    openssl-users@openssl.org
> Automated List Manager                           majord...@openssl.org
>

Reply via email to