caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Unix.connect for non-blocking sockets on Windows
@ 2012-09-14 13:53 Romain Bardou
  2012-09-14 14:27 ` Jérémie Dimino
  0 siblings, 1 reply; 7+ messages in thread
From: Romain Bardou @ 2012-09-14 13:53 UTC (permalink / raw)
  To: caml-list

Hello,

It seems, from the manual[1] that sockets of the Unix module are fully 
implemented on Windows. It also seems, from other googling, that 
non-blocking sockets are also implemented.

[1] http://caml.inria.fr/pub/docs/manual-ocaml/manual036.html

However, when I run the Unix.connect command on Windows, I get:

   Unix_error(EWOULDBLOCK, "connect", "")

I'm using OCaml 3.12.1 on Windows using the (older) installer from 
Jonathan, which uses mingw if I'm not mistaken. The code I use is more 
or less equivalent to:

   open Unix
   let address = "xxx.xxx.xxx.xxx" in (* some IP for IPv4 *)
   let port = 9543 in
   let fd = socket PF_INET SOCK_STREAM 0 in
   set_nonblock fd;
   connect fd (ADDR_INET (Unix.inet_addr_of_string address, port))

Is this a known issue?

Thanks,

-- 
Romain Bardou

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Unix.connect for non-blocking sockets on Windows
  2012-09-14 13:53 [Caml-list] Unix.connect for non-blocking sockets on Windows Romain Bardou
@ 2012-09-14 14:27 ` Jérémie Dimino
  2012-09-14 15:21   ` Jerome Vouillon
  0 siblings, 1 reply; 7+ messages in thread
From: Jérémie Dimino @ 2012-09-14 14:27 UTC (permalink / raw)
  To: Romain Bardou; +Cc: caml-list

Hi,

Le Fri, 14 Sep 2012 15:53:24 +0200,
Romain Bardou <romain.bardou@inria.fr> a écrit :

>    open Unix
>    let address = "xxx.xxx.xxx.xxx" in (* some IP for IPv4 *)
>    let port = 9543 in
>    let fd = socket PF_INET SOCK_STREAM 0 in
>    set_nonblock fd;
>    connect fd (ADDR_INET (Unix.inet_addr_of_string address, port))

If the socket is in non-blocking mode and connect blocks, then you get
a Unix.EWOULDBLOCK error. According to the MSDN documentation, if
connect fails with EWOULDBLOCK, you have to wait for the socket to
become writeable then call connect again which will fail with EISCONN
if the connection succeeded.

-- 
Jérémie

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Unix.connect for non-blocking sockets on Windows
  2012-09-14 14:27 ` Jérémie Dimino
@ 2012-09-14 15:21   ` Jerome Vouillon
  2012-09-14 15:26     ` Romain Bardou
  2012-09-14 15:33     ` Jérémie Dimino
  0 siblings, 2 replies; 7+ messages in thread
From: Jerome Vouillon @ 2012-09-14 15:21 UTC (permalink / raw)
  To: Romain Bardou; +Cc: caml-list, Jérémie Dimino

Hi Jérémie,

On Fri, Sep 14, 2012 at 04:27:17PM +0200, Jérémie Dimino wrote:
> Le Fri, 14 Sep 2012 15:53:24 +0200,
> Romain Bardou <romain.bardou@inria.fr> a écrit :
> 
> >    open Unix
> >    let address = "xxx.xxx.xxx.xxx" in (* some IP for IPv4 *)
> >    let port = 9543 in
> >    let fd = socket PF_INET SOCK_STREAM 0 in
> >    set_nonblock fd;
> >    connect fd (ADDR_INET (Unix.inet_addr_of_string address, port))
> 
> If the socket is in non-blocking mode and connect blocks, then you get
> a Unix.EWOULDBLOCK error. According to the MSDN documentation, if
> connect fails with EWOULDBLOCK, you have to wait for the socket to
> become writeable then call connect again which will fail with EISCONN
> if the connection succeeded.

This is not quite what I can read in the MSDN documentation...

  "[...] it is not recommended that applications use multiple calls to
   connect to detect connection completion. If they do, they must be
   prepared to handle WSAEINVAL and WSAEWOULDBLOCK error values the
   same way that they handle WSAEALREADY, to assure robust operation"

You should use Unix.getsockopt_error (just like under Unix) to check
for errors when the socket becomes writable, rather than call connect
again.

-- Jérôme

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Unix.connect for non-blocking sockets on Windows
  2012-09-14 15:21   ` Jerome Vouillon
@ 2012-09-14 15:26     ` Romain Bardou
  2012-09-14 15:33     ` Jérémie Dimino
  1 sibling, 0 replies; 7+ messages in thread
From: Romain Bardou @ 2012-09-14 15:26 UTC (permalink / raw)
  To: Jerome Vouillon; +Cc: caml-list, Jérémie Dimino

Le 14/09/2012 17:21, Jerome Vouillon a écrit :
> Hi Jérémie,
>
> On Fri, Sep 14, 2012 at 04:27:17PM +0200, Jérémie Dimino wrote:
>> Le Fri, 14 Sep 2012 15:53:24 +0200,
>> Romain Bardou<romain.bardou@inria.fr>  a écrit :
>>
>>>     open Unix
>>>     let address = "xxx.xxx.xxx.xxx" in (* some IP for IPv4 *)
>>>     let port = 9543 in
>>>     let fd = socket PF_INET SOCK_STREAM 0 in
>>>     set_nonblock fd;
>>>     connect fd (ADDR_INET (Unix.inet_addr_of_string address, port))
>>
>> If the socket is in non-blocking mode and connect blocks, then you get
>> a Unix.EWOULDBLOCK error. According to the MSDN documentation, if
>> connect fails with EWOULDBLOCK, you have to wait for the socket to
>> become writeable then call connect again which will fail with EISCONN
>> if the connection succeeded.
>
> This is not quite what I can read in the MSDN documentation...
>
>    "[...] it is not recommended that applications use multiple calls to
>     connect to detect connection completion. If they do, they must be
>     prepared to handle WSAEINVAL and WSAEWOULDBLOCK error values the
>     same way that they handle WSAEALREADY, to assure robust operation"
>
> You should use Unix.getsockopt_error (just like under Unix) to check
> for errors when the socket becomes writable, rather than call connect
> again.

Oh so actually it's even easier than I thought. From what you're saying 
I just need to treat the EWOULDBLOCK case as if it was EINPROGRESS 
(which is what is returned by connect on Linux) and the rest is the same.

Thanks to both of you!

-- 
Romain Bardou

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Unix.connect for non-blocking sockets on Windows
  2012-09-14 15:21   ` Jerome Vouillon
  2012-09-14 15:26     ` Romain Bardou
@ 2012-09-14 15:33     ` Jérémie Dimino
  2012-09-14 15:46       ` Romain Bardou
  2012-10-10 14:14       ` Jerome Vouillon
  1 sibling, 2 replies; 7+ messages in thread
From: Jérémie Dimino @ 2012-09-14 15:33 UTC (permalink / raw)
  To: Jerome Vouillon; +Cc: Romain Bardou, caml-list

Le Fri, 14 Sep 2012 17:21:25 +0200,
Jerome Vouillon <Jerome.Vouillon@pps.jussieu.fr> a écrit :

> You should use Unix.getsockopt_error (just like under Unix) to check
> for errors when the socket becomes writable, rather than call connect
> again.

Acutally, last time i tried (on Windows XP) it was not working,
Unix.getsockopt_error was returning None but the socket was not
connected.

-- 
Jérémie

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Unix.connect for non-blocking sockets on Windows
  2012-09-14 15:33     ` Jérémie Dimino
@ 2012-09-14 15:46       ` Romain Bardou
  2012-10-10 14:14       ` Jerome Vouillon
  1 sibling, 0 replies; 7+ messages in thread
From: Romain Bardou @ 2012-09-14 15:46 UTC (permalink / raw)
  To: Jérémie Dimino; +Cc: Jerome Vouillon, caml-list

Le 14/09/2012 17:33, Jérémie Dimino a écrit :
> Le Fri, 14 Sep 2012 17:21:25 +0200,
> Jerome Vouillon<Jerome.Vouillon@pps.jussieu.fr>  a écrit :
>
>> You should use Unix.getsockopt_error (just like under Unix) to check
>> for errors when the socket becomes writable, rather than call connect
>> again.
>
> Acutally, last time i tried (on Windows XP) it was not working,
> Unix.getsockopt_error was returning None but the socket was not
> connected.
>

I just tried it (on Windows XP) and it works. But the connection is very 
slow for some reason, with about 30s between each message. I probably 
have to flush the socket or something.

Cheers,

-- 
Romain

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Unix.connect for non-blocking sockets on Windows
  2012-09-14 15:33     ` Jérémie Dimino
  2012-09-14 15:46       ` Romain Bardou
@ 2012-10-10 14:14       ` Jerome Vouillon
  1 sibling, 0 replies; 7+ messages in thread
From: Jerome Vouillon @ 2012-10-10 14:14 UTC (permalink / raw)
  To: Jérémie Dimino; +Cc: caml-list

On Fri, Sep 14, 2012 at 05:33:50PM +0200, Jérémie Dimino wrote:
> Le Fri, 14 Sep 2012 17:21:25 +0200,
> Jerome Vouillon <Jerome.Vouillon@pps.jussieu.fr> a écrit :
> 
> > You should use Unix.getsockopt_error (just like under Unix) to check
> > for errors when the socket becomes writable, rather than call connect
> > again.
> 
> Actually, last time i tried (on Windows XP) it was not working,
> Unix.getsockopt_error was returning None but the socket was not
> connected.

I believe that this is due to a bug in the implementation of
Unix.select ( http://caml.inria.fr/mantis/view.php?id=5783 ). As a
result, this function returns immediately and wrongly reports that
the socket is writable. (Since OCaml 4, this bug only occurs when
simultaneously selecting a non-socket file descriptor.)

Thus, calling Unix.connect again instead of Unix.getsockopt_error is
just a workaround for this bug: you are busy waiting for the
connection to complete. (And, by the way, the secont call to
Unix.connect will fail with the error code EALREADY rather that
EWOULDBLOCK with Windows 8.)

-- Jerome



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-10-10 14:15 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-14 13:53 [Caml-list] Unix.connect for non-blocking sockets on Windows Romain Bardou
2012-09-14 14:27 ` Jérémie Dimino
2012-09-14 15:21   ` Jerome Vouillon
2012-09-14 15:26     ` Romain Bardou
2012-09-14 15:33     ` Jérémie Dimino
2012-09-14 15:46       ` Romain Bardou
2012-10-10 14:14       ` Jerome Vouillon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).