caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Error binding socket
@ 2005-11-09 12:33 Maurizio Colucci
  2005-11-09 12:55 ` [Caml-list] " Gerd Stolpmann
  2005-11-09 13:29 ` skaller
  0 siblings, 2 replies; 5+ messages in thread
From: Maurizio Colucci @ 2005-11-09 12:33 UTC (permalink / raw)
  To: caml-list

Hi there. For my free tennis game (http://freetennis.sf.net), I get an
error binding the socket to a port. (Unix_error 50, "bind"). The error
description is "address already in use".

This error only happens the *second* time I start the program. It is
as if the port had not been freed and were still in use. The system is
GNU/Linux Ubuntu Breezy.

However, if I wait about 1minute, or I start the program specifying a
different port, the problem does not happen. It is as if Linux were
freeing the port with a delay.

At first glance, I thought I was not using Unix.close or Unix.socket
correctly, but this does not seem to be the case.

The code is freely available, however here is the relevant part of the code:

(* Here is the socket initialization phase, for both client and server: *)

	      let serverData =
		  let rec tryToConnectNTimes n ~soc ~inet_a ~port=
		      try
			  Unix.connect  soc (Unix.ADDR_INET  (inet_a, port) )
		      with Unix.Unix_error _ ->
			  if n = 0 then
			      raise CouldNotConnectToServer
			  else
			      ( print_endline ( "The server is down. Retrying " ^
string_of_int (n-1) ^ " times.");
				Unix.sleep 1;
				tryToConnectNTimes (n-1) ~soc ~inet_a ~port )
		  in
		  if !server  then
		      let soc = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
		      (
			  (try
			      Unix.bind soc (Unix.ADDR_INET (Unix.inet_addr_any, !port))
			  with Unix.Unix_error (err, _, _) ->
			      (print_endline ("Error: " ^(Unix.error_message err) ^ ". This
is a known bug. Please wait a few seconds or simply change the port
number with the -port option");
			       exit 0 ));
			  Unix.listen soc 5;
			  print_endline "waiting for client to connect...";
			  let clientSocket, _ = Unix.accept soc in
			  Server ( (soc, clientSocket), Unix.in_channel_of_descr
clientSocket, Unix.out_channel_of_descr clientSocket)
		      )

		  else  if 0 != compare !client  ""  then
		      let soc = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
		      let inet_a = Unix.inet_addr_of_string !client in
		      print_endline "Connecting to server...";
		      ( tryToConnectNTimes 60 ~soc ~inet_a ~port:!port;
			print_endline "Connected to server";
			Client (soc, Unix.in_channel_of_descr  soc, Unix.out_channel_of_descr soc) )
		  else
		      NeitherServerNorClient
	      in


(*... and here is the socket cleanup code *)

	      (match serverData with
		       (* the rule is to shutdown before you close,
			  but this is often automatic. see sockets
			  howto.

		       *)
		   | Server( (sock, clientSocket), inc, outc) ->
			 print_endline "Shutting down socket";
  			 Unix.shutdown clientSocket Unix.SHUTDOWN_ALL ;
  			 Unix.shutdown sock Unix.SHUTDOWN_ALL ;
  			 Unix.close clientSocket;
  			 Unix.close sock;
		   | Client ( sock, inc, outc) ->
			 print_endline "Shutting down socket";
  			 Unix.shutdown sock Unix.SHUTDOWN_ALL  ;
 			 Unix.close sock;

		   | NeitherServerNorClient -> ());



One doubt I have is the following: in the server code, must I call
close on sock or in clientSocket?

If I am doing something wrong, could you please tell me. :-) Thank you



Maurizio


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

* Re: [Caml-list] Error binding socket
  2005-11-09 12:33 Error binding socket Maurizio Colucci
@ 2005-11-09 12:55 ` Gerd Stolpmann
  2005-11-09 13:02   ` Maurizio Colucci
  2005-11-09 13:29 ` skaller
  1 sibling, 1 reply; 5+ messages in thread
From: Gerd Stolpmann @ 2005-11-09 12:55 UTC (permalink / raw)
  To: Maurizio Colucci; +Cc: caml-list

Am Mittwoch, den 09.11.2005, 13:33 +0100 schrieb Maurizio Colucci:
> Hi there. For my free tennis game (http://freetennis.sf.net), I get an
> error binding the socket to a port. (Unix_error 50, "bind"). The error
> description is "address already in use".
> 
> This error only happens the *second* time I start the program. It is
> as if the port had not been freed and were still in use. The system is
> GNU/Linux Ubuntu Breezy.
> 
> However, if I wait about 1minute, or I start the program specifying a
> different port, the problem does not happen. It is as if Linux were
> freeing the port with a delay.

This is the default behaviour: Linux (and all other OS, too) has this
delay to ensure that pending connection attempts are properly reset.
This is reasonable for anonymous ports, but not for well-known service
ports. You can disable this with the socket option REUSEADDR.

Gerd

> 
> At first glance, I thought I was not using Unix.close or Unix.socket
> correctly, but this does not seem to be the case.
> 
> The code is freely available, however here is the relevant part of the code:
> 
> (* Here is the socket initialization phase, for both client and server: *)
> 
> 	      let serverData =
> 		  let rec tryToConnectNTimes n ~soc ~inet_a ~port=
> 		      try
> 			  Unix.connect  soc (Unix.ADDR_INET  (inet_a, port) )
> 		      with Unix.Unix_error _ ->
> 			  if n = 0 then
> 			      raise CouldNotConnectToServer
> 			  else
> 			      ( print_endline ( "The server is down. Retrying " ^
> string_of_int (n-1) ^ " times.");
> 				Unix.sleep 1;
> 				tryToConnectNTimes (n-1) ~soc ~inet_a ~port )
> 		  in
> 		  if !server  then
> 		      let soc = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
> 		      (
> 			  (try
> 			      Unix.bind soc (Unix.ADDR_INET (Unix.inet_addr_any, !port))
> 			  with Unix.Unix_error (err, _, _) ->
> 			      (print_endline ("Error: " ^(Unix.error_message err) ^ ". This
> is a known bug. Please wait a few seconds or simply change the port
> number with the -port option");
> 			       exit 0 ));
> 			  Unix.listen soc 5;
> 			  print_endline "waiting for client to connect...";
> 			  let clientSocket, _ = Unix.accept soc in
> 			  Server ( (soc, clientSocket), Unix.in_channel_of_descr
> clientSocket, Unix.out_channel_of_descr clientSocket)
> 		      )
> 
> 		  else  if 0 != compare !client  ""  then
> 		      let soc = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
> 		      let inet_a = Unix.inet_addr_of_string !client in
> 		      print_endline "Connecting to server...";
> 		      ( tryToConnectNTimes 60 ~soc ~inet_a ~port:!port;
> 			print_endline "Connected to server";
> 			Client (soc, Unix.in_channel_of_descr  soc, Unix.out_channel_of_descr soc) )
> 		  else
> 		      NeitherServerNorClient
> 	      in
> 
> 
> (*... and here is the socket cleanup code *)
> 
> 	      (match serverData with
> 		       (* the rule is to shutdown before you close,
> 			  but this is often automatic. see sockets
> 			  howto.
> 
> 		       *)
> 		   | Server( (sock, clientSocket), inc, outc) ->
> 			 print_endline "Shutting down socket";
>   			 Unix.shutdown clientSocket Unix.SHUTDOWN_ALL ;
>   			 Unix.shutdown sock Unix.SHUTDOWN_ALL ;
>   			 Unix.close clientSocket;
>   			 Unix.close sock;
> 		   | Client ( sock, inc, outc) ->
> 			 print_endline "Shutting down socket";
>   			 Unix.shutdown sock Unix.SHUTDOWN_ALL  ;
>  			 Unix.close sock;
> 
> 		   | NeitherServerNorClient -> ());
> 
> 
> 
> One doubt I have is the following: in the server code, must I call
> close on sock or in clientSocket?
> 
> If I am doing something wrong, could you please tell me. :-) Thank you
> 
> 
> 
> Maurizio
> 
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
> 
-- 
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Telefon: 06151/153855                  Telefax: 06151/997714
------------------------------------------------------------


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

* Re: [Caml-list] Error binding socket
  2005-11-09 12:55 ` [Caml-list] " Gerd Stolpmann
@ 2005-11-09 13:02   ` Maurizio Colucci
  0 siblings, 0 replies; 5+ messages in thread
From: Maurizio Colucci @ 2005-11-09 13:02 UTC (permalink / raw)
  Cc: caml-list

Thank you, that's exactly the answer I was looking for!

2005/11/9, Gerd Stolpmann <info@gerd-stolpmann.de>:
> Am Mittwoch, den 09.11.2005, 13:33 +0100 schrieb Maurizio Colucci:
> > Hi there. For my free tennis game (http://freetennis.sf.net), I get an
> > error binding the socket to a port. (Unix_error 50, "bind"). The error
> > description is "address already in use".
> >
> > This error only happens the *second* time I start the program. It is
> > as if the port had not been freed and were still in use. The system is
> > GNU/Linux Ubuntu Breezy.
> >
> > However, if I wait about 1minute, or I start the program specifying a
> > different port, the problem does not happen. It is as if Linux were
> > freeing the port with a delay.
>
> This is the default behaviour: Linux (and all other OS, too) has this
> delay to ensure that pending connection attempts are properly reset.
> This is reasonable for anonymous ports, but not for well-known service
> ports. You can disable this with the socket option REUSEADDR.
>
> Gerd
>
> >
> > At first glance, I thought I was not using Unix.close or Unix.socket
> > correctly, but this does not seem to be the case.
> >
> > The code is freely available, however here is the relevant part of the code:
> >
> > (* Here is the socket initialization phase, for both client and server: *)
> >
> >             let serverData =
> >                 let rec tryToConnectNTimes n ~soc ~inet_a ~port=
> >                     try
> >                         Unix.connect  soc (Unix.ADDR_INET  (inet_a, port) )
> >                     with Unix.Unix_error _ ->
> >                         if n = 0 then
> >                             raise CouldNotConnectToServer
> >                         else
> >                             ( print_endline ( "The server is down. Retrying " ^
> > string_of_int (n-1) ^ " times.");
> >                               Unix.sleep 1;
> >                               tryToConnectNTimes (n-1) ~soc ~inet_a ~port )
> >                 in
> >                 if !server  then
> >                     let soc = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
> >                     (
> >                         (try
> >                             Unix.bind soc (Unix.ADDR_INET (Unix.inet_addr_any, !port))
> >                         with Unix.Unix_error (err, _, _) ->
> >                             (print_endline ("Error: " ^(Unix.error_message err) ^ ". This
> > is a known bug. Please wait a few seconds or simply change the port
> > number with the -port option");
> >                              exit 0 ));
> >                         Unix.listen soc 5;
> >                         print_endline "waiting for client to connect...";
> >                         let clientSocket, _ = Unix.accept soc in
> >                         Server ( (soc, clientSocket), Unix.in_channel_of_descr
> > clientSocket, Unix.out_channel_of_descr clientSocket)
> >                     )
> >
> >                 else  if 0 != compare !client  ""  then
> >                     let soc = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
> >                     let inet_a = Unix.inet_addr_of_string !client in
> >                     print_endline "Connecting to server...";
> >                     ( tryToConnectNTimes 60 ~soc ~inet_a ~port:!port;
> >                       print_endline "Connected to server";
> >                       Client (soc, Unix.in_channel_of_descr  soc, Unix.out_channel_of_descr soc) )
> >                 else
> >                     NeitherServerNorClient
> >             in
> >
> >
> > (*... and here is the socket cleanup code *)
> >
> >             (match serverData with
> >                      (* the rule is to shutdown before you close,
> >                         but this is often automatic. see sockets
> >                         howto.
> >
> >                      *)
> >                  | Server( (sock, clientSocket), inc, outc) ->
> >                        print_endline "Shutting down socket";
> >                        Unix.shutdown clientSocket Unix.SHUTDOWN_ALL ;
> >                        Unix.shutdown sock Unix.SHUTDOWN_ALL ;
> >                        Unix.close clientSocket;
> >                        Unix.close sock;
> >                  | Client ( sock, inc, outc) ->
> >                        print_endline "Shutting down socket";
> >                        Unix.shutdown sock Unix.SHUTDOWN_ALL  ;
> >                        Unix.close sock;
> >
> >                  | NeitherServerNorClient -> ());
> >
> >
> >
> > One doubt I have is the following: in the server code, must I call
> > close on sock or in clientSocket?
> >
> > If I am doing something wrong, could you please tell me. :-) Thank you
> >
> >
> >
> > Maurizio
> >
> > _______________________________________________
> > Caml-list mailing list. Subscription management:
> > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> > Archives: http://caml.inria.fr
> > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> > Bug reports: http://caml.inria.fr/bin/caml-bugs
> >
> --
> ------------------------------------------------------------
> Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany
> gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
> Telefon: 06151/153855                  Telefax: 06151/997714
> ------------------------------------------------------------
>
>


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

* Re: [Caml-list] Error binding socket
  2005-11-09 12:33 Error binding socket Maurizio Colucci
  2005-11-09 12:55 ` [Caml-list] " Gerd Stolpmann
@ 2005-11-09 13:29 ` skaller
  2005-11-09 14:36   ` Gerd Stolpmann
  1 sibling, 1 reply; 5+ messages in thread
From: skaller @ 2005-11-09 13:29 UTC (permalink / raw)
  To: Maurizio Colucci; +Cc: caml-list

On Wed, 2005-11-09 at 13:33 +0100, Maurizio Colucci wrote:
> Hi there. For my free tennis game (http://freetennis.sf.net), I get an
> error binding the socket to a port. (Unix_error 50, "bind"). The error
> description is "address already in use".
> 
> This error only happens the *second* time I start the program. It is
> as if the port had not been freed and were still in use. The system is
> GNU/Linux Ubuntu Breezy.
> 
> However, if I wait about 1minute, or I start the program specifying a
> different port, the problem does not happen. It is as if Linux were
> freeing the port with a delay.

This is standard Unix behaviour. 

use the setsockopt() function, these options may help 
(from man 7 socket), I forget the Ocaml for this, but I know
it can be done because I had exactly the same problem myself once.

       SO_REUSEADDR
              Indicates that the rules used in validating addresses
supplied in a bind(2) call
              should  allow  reuse  of  local addresses. For PF_INET
sockets this means that a
              socket may bind, except when there is an active listening
socket  bound  to  the
              address.   When the listening socket is bound to
INADDR_ANY with a specific port
              then it is not possible to bind to this port for any local
address.

       SO_LINGER
              Sets or gets the SO_LINGER option. The argument is a
linger structure.

              struct linger {
                  int   l_onoff;    /* linger active */
                  int   l_linger;   /* how many seconds to linger for */
              };

              When enabled, a close(2) or shutdown(2) will not return
until  all  queued  mes‐
              sages  for the socket have been successfully sent or the
linger timeout has been
              reached. Otherwise, the call returns immediately and the
closing is done in  the
              background.   When the socket is closed as part of
exit(2), it always lingers in
              the background.


-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


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

* Re: [Caml-list] Error binding socket
  2005-11-09 13:29 ` skaller
@ 2005-11-09 14:36   ` Gerd Stolpmann
  0 siblings, 0 replies; 5+ messages in thread
From: Gerd Stolpmann @ 2005-11-09 14:36 UTC (permalink / raw)
  To: skaller; +Cc: Maurizio Colucci, caml-list

Am Donnerstag, den 10.11.2005, 00:29 +1100 schrieb skaller:
> On Wed, 2005-11-09 at 13:33 +0100, Maurizio Colucci wrote:
> > Hi there. For my free tennis game (http://freetennis.sf.net), I get an
> > error binding the socket to a port. (Unix_error 50, "bind"). The error
> > description is "address already in use".
> > 
> > This error only happens the *second* time I start the program. It is
> > as if the port had not been freed and were still in use. The system is
> > GNU/Linux Ubuntu Breezy.
> > 
> > However, if I wait about 1minute, or I start the program specifying a
> > different port, the problem does not happen. It is as if Linux were
> > freeing the port with a delay.
> 

>        SO_LINGER

Usually you need lingering only if the server socket closes the
connection (fully) and wants to be sure everything is transmitted to the
client. Only very few protocols need this.

Gerd

>               Sets or gets the SO_LINGER option. The argument is a
> linger structure.
> 
>               struct linger {
>                   int   l_onoff;    /* linger active */
>                   int   l_linger;   /* how many seconds to linger for */
>               };
> 
>               When enabled, a close(2) or shutdown(2) will not return
> until  all  queued  mes‐
>               sages  for the socket have been successfully sent or the
> linger timeout has been
>               reached. Otherwise, the call returns immediately and the
> closing is done in  the
>               background.   When the socket is closed as part of
> exit(2), it always lingers in
>               the background.
> 
> 
-- 
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Telefon: 06151/153855                  Telefax: 06151/997714
------------------------------------------------------------


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

end of thread, other threads:[~2005-11-09 14:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-11-09 12:33 Error binding socket Maurizio Colucci
2005-11-09 12:55 ` [Caml-list] " Gerd Stolpmann
2005-11-09 13:02   ` Maurizio Colucci
2005-11-09 13:29 ` skaller
2005-11-09 14:36   ` Gerd Stolpmann

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).