Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why connect() does not block?

12 views
Skip to first unread message

ale

unread,
Aug 27, 2009, 8:20:44 AM8/27/09
to a.maz...@list-group.com
Hello,
Could you explain me why the connect() does not block?


int my_socketpair(SOCKET socks[2])
{
SOCKET listener = INVALID_SOCKET;
int addrlen = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));

if(socks){
socks[0] = socks[1] = INVALID_SOCKET;
if((listener=socket(AF_INET, SOCK_STREAM, 0))!=INVALID_SOCKET){
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = 0;

if(bind(listener, (const struct sockaddr*)&addr, sizeof(struct
sockaddr_in))!=SOCKET_ERROR){
if(getsockname(listener, (struct sockaddr*)&addr, &addrlen)!
=SOCKET_ERROR){
if(listen(listener, 1)!=SOCKET_ERROR){
if((socks[0]=socket(AF_INET, SOCK_STREAM, 0))!=INVALID_SOCKET){
if(connect(socks[0], (const struct sockaddr*)&addr, sizeof
(addr))!=SOCKET_ERROR){
/*
* int ret = send(socks[0], "foo", strlen("foo"), 0);
*/
if((socks[1]=accept(listener, NULL, NULL))!=INVALID_SOCKET){
/*
* char foo[sizeof("foo")] = {'\0'};
* int ret = recv(socks[1], foo, sizeof(foo), 0);
*/
closesocket(listener);
return 0;
}
}
}
}
}
}
if(listener!=INVALID_SOCKET){
closesocket(listener);
listener = INVALID_SOCKET;
}
if(socks[0]!=INVALID_SOCKET){
closesocket(socks[0]);
socks[0] = INVALID_SOCKET;
}
if(socks[1]!=INVALID_SOCKET){
closesocket(socks[1]);
socks[1] = INVALID_SOCKET;
}
}
}else{
WSASetLastError(WSAEINVAL);
}
return SOCKET_ERROR;
}


Please note that setting the FIONBIO socket option to set the non-
blocking mode, then I get EWOULDBLOCK as I try to connect() .

Again, plese note that if I perform a send() before the accept(), but
after the connect(), it works without error and the data is rightly
received with recv() immedietely after the accept().

I thought it could depend on the loopback address or on the ephemeral
port on the listener...but I didn't find anything on the connect()
specification.

Have you ever had a similiar problem?

Many thanks in advance,
-- Alessio


Peter Duniho

unread,
Aug 27, 2009, 1:15:30 PM8/27/09
to
On Thu, 27 Aug 2009 05:20:44 -0700, ale <mazz...@cli.di.unipi.it> wrote:

> Hello,
> Could you explain me why the connect() does not block?
>

> [...]


> Again, plese note that if I perform a send() before the accept(), but
> after the connect(), it works without error and the data is rightly
> received with recv() immedietely after the accept().
>
> I thought it could depend on the loopback address or on the ephemeral
> port on the listener...but I didn't find anything on the connect()
> specification.
>
> Have you ever had a similiar problem?

I'm unclear as to why the lack of blocking is a _problem_. Perhaps you
could elaborate.

The connect succeeds, because that's what the network stack allows. Your
client sees a successful connection, processed on behalf of the listening
socket by the network stack. The network stack also buffers a certain
amount of data, so as long as you don't try to send something unreasonably
long before accepting the socket later, you'll get all that data in a
later receive.

The code you posted is code that should never appear in a real Winsock
program anyway, but it would not even work if the call to connect()
blocked. Why would someone write bad code, and then ask why they couldn't
get it to fail? Is there some practical need you have for this bad code
to not work?

Pete

ale

unread,
Aug 28, 2009, 3:38:10 AM8/28/09
to a.maz...@list-group.com
> I'm unclear as to why the lack of blocking is a _problem_.  Perhaps you  
> could elaborate.
>
> The connect succeeds, because that's what the network stack allows.  Your  
> client sees a successful connection, processed on behalf of the listening  
> socket by the network stack.  The network stack also buffers a certain  
> amount of data, so as long as you don't try to send something unreasonably  
> long before accepting the socket later, you'll get all that data in a  
> later receive.
>
> The code you posted is code that should never appear in a real Winsock  
> program anyway, but it would not even work if the call to connect()  
> blocked.  Why would someone write bad code, and then ask why they couldn't  
> get it to fail?  Is there some practical need you have for this bad code  
> to not work?
>
> Pete

Thanks for your reply.

Actually the lack of blocking would not be a _problem_, provided that
it is not a Winsock 'bug'.
Since that behaviour is not documented, I was concerned it was a sort
of 'bug', and it could be fixed at the first windows update...
If it is not a 'bug', maybe interesting to know that blocking socket
connect(), like in the code I posted, performs better than setting the
socket to be non-blocking that, besides, returns EWOULDBLOCK.

Why setting the socket to be non-blocking the connect() returns
EWOULDBLOCK also in a similiar situation, in which actually it 'would
not block'?


Why do you think the code I posted should never appear in a real
Winsock program?
Actually I need to implement the socketpair() function (that is
currently used primarily with UNIX domain sockets).

Many thanks for your help.
-- Ale

Peter Duniho

unread,
Aug 28, 2009, 3:47:24 AM8/28/09
to
On Fri, 28 Aug 2009 00:38:10 -0700, ale <mazz...@cli.di.unipi.it> wrote:

> [...]


> If it is not a 'bug', maybe interesting to know that blocking socket
> connect(), like in the code I posted, performs better than setting the
> socket to be non-blocking that, besides, returns EWOULDBLOCK.

It only doesn't block if the connecting can be resolved immediately. As
for whether it's documented, I haven't gone and looked specifically for
that, but I would guess that there's something _somewhere_ that at least
by implication describes the behavior.

That's not to say that the behavior is _guaranteed_. Just that it's not
unexpected.

> Why setting the socket to be non-blocking the connect() returns
> EWOULDBLOCK also in a similiar situation, in which actually it 'would
> not block'?

If the connection can be resolved immediately, I would expect connect()
would return a success. Otherwise, you would get EWOULDBLOCK. Note that
"immediate" is relative. For the purposes of the API, it probably can't
normally complete immediately, but would be so fast that if you're sitting
there watching the program run it would _look_ like it was immediate.

In other words, don't confuse "returns quickly" with "returns
immediately". On a blocking socket, it could in fact be blocking, but in
a way that you don't really notice (in fact, I expect that's the common
case).

> Why do you think the code I posted should never appear in a real
> Winsock program?

At the very least, because AFAIK Winsock doesn't give you any guarantee
that the connect() method won't block indefinitely, and so the code has
the potential to self-deadlock. I think there are other reasons, but this
basic issue of having the same thread trying to do things that may depend
on operations implemented later in the thread just seems very wrong to me.

> Actually I need to implement the socketpair() function (that is
> currently used primarily with UNIX domain sockets).

Sorry, not familiar with that function. I looked at the man page, but it
didn't really explain in a useful way precisely what the purpose of the
function is, or why you'd want to use it.

Pete

ale

unread,
Aug 28, 2009, 4:24:52 AM8/28/09
to a.maz...@list-group.com
Hello,

> It only doesn't block if the connecting can be resolved immediately.  

I have been thinking that 'immediately' means that the connect() has
a
very little timeout, and it doesn't block if the server -accepts- the
connection within that timeout.
Obviously in the meantime the connect should block!
Any other behaviour makes the connect() liar, because the connection
isn't actually performed.

> Sorry, not familiar with that function.  I looked at the man page, but it  
> didn't really explain in a useful way precisely what the purpose of the  
> function is, or why you'd want to use it.

What you get by means of socketpair() is trivially a two-way pipe,
that is usable between two process (father and son), or two threads in
the same process,
and it is selectable by means of select() together with other socket
descriptors.
May be used, for example, to wake-up a select with timeout, when a
certain internal event occours.

Many thanks for your help,
-- Ale


Peter Duniho

unread,
Aug 28, 2009, 5:15:14 AM8/28/09
to
On Fri, 28 Aug 2009 01:24:52 -0700, ale <mazz...@cli.di.unipi.it> wrote:

> Hello,
>
>> It only doesn't block if the connecting can be resolved immediately.  
>
> I have been thinking that 'immediately' means that the connect() has a
> very little timeout,

No. "Immediately" means exactly that: without _any_ delay. Not "very
little timeout", but "no timeout at all".

> and it doesn't block if the server -accepts- the
> connection within that timeout.

I don't think that's correct. If the socket is in blocking mode, then
connect() blocks until there's a connection or an error.

> Obviously in the meantime the connect should block!
> Any other behaviour makes the connect() liar, because the connection
> isn't actually performed.

If connect() function returns without an error, whether the socket is in
blocking mode or not, then there is a TCP/IP connection. The fact that
you haven't called accept() using the listening socket is irrelevant, as I
explained earlier.

>> Sorry, not familiar with that function.  I looked at the man page, but
>> it  
>> didn't really explain in a useful way precisely what the purpose of the
>> function is, or why you'd want to use it.
>
> What you get by means of socketpair() is trivially a two-way pipe,
> that is usable between two process (father and son), or two threads in

> the same process, [...]

Okay, I see. I am not convinced that the code you posted is a safe way to
do that, but a) I see the attraction to writing it in a single thread like
that, and b) I'm not enough of a Winsock expert to know for sure whether
there's a true deadlock potential (the code clearly has a theoretical
deadlock potential, but it's possible there's some guarantee in Winsock
I'm not aware of that would ensure against that).

Personally, I'd probably put the sockets in non-blocking mode and use
select() to ensure that the single thread can always complete both the
connect() and the accept() call as necessary, without blocking the other.
But I admit, that's more complicated code.

Pete

ale

unread,
Aug 28, 2009, 6:02:19 AM8/28/09
to
> Personally, I'd probably put the sockets in non-blocking mode and use  
> select() to ensure that the single thread can always complete both the  
> connect() and the accept() call as necessary, without blocking the other.  
> But I admit, that's more complicated code.

In fact, I will do so for sure.
I just have to add two statements! :-)
It's a pity that performances of connect() will degrade...

Many thanks for the interesting discussion.
-- Ale

Peter Duniho

unread,
Aug 28, 2009, 1:35:44 PM8/28/09
to
On Fri, 28 Aug 2009 03:02:19 -0700, ale <mazz...@cli.di.unipi.it> wrote:

>> Personally, I'd probably put the sockets in non-blocking mode and use  
>> select() to ensure that the single thread can always complete both the  
>> connect() and the accept() call as necessary, without blocking the
>> other.  
>> But I admit, that's more complicated code.
>
> In fact, I will do so for sure.
> I just have to add two statements! :-)
> It's a pity that performances of connect() will degrade...

It won't degrade at all.

0 new messages