digitalmars.D.learn - How to cleanup after Socket.bind on Linux?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (87/87) Aug 26 2013 The following simple socket example is trying to cleanup after itself,
- dnewbie (2/4) Aug 26 2013 It works on Windows7, no need to wait.
- Regan Heath (36/43) Aug 27 2013 =
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/7) Aug 27 2013 That worked. I copied the following line from std/socket.d:
The following simple socket example is trying to cleanup after itself, 
except the bind() call. As I repeat in the QUESTION comment below, I 
have read the man page of bind and I know that I need to unlink a path. 
How can I get that path?
The program waits on localhost:8080, receives N number of data and 
responds with "Hello World!".
The problem is, currently the program apparently leakes some resources. 
It cannot be started a second time for 8080 still being in use, unless 
you wait for several seconds, presumably until the OS does the cleanup.
import std.stdio;
import std.socket;
import std.string;
enum port = 8080;
void main()
{
     server();
}
void server()
{
     // Prepare the socket
     auto listener = new TcpSocket();
     scope (exit) {
         writefln("Shutting down and closing the listener");
         listener.shutdown(SocketShutdown.BOTH);
         listener.close();
     }
     /*
      * The port to listen to
      *
      * Note that the following perhaps naive code does not work on OSX. Try
      * the following line instead:
      *
      *   listener.bind(new InternetAddress(port));
      */
     Address[] addresses = getAddress("localhost", port);
     writefln("Addresses: %s", addresses);
     auto address = addresses[0];
     writefln("Address: %s", address);
     listener.bind(address);
     scope (exit) {
         /*
          * QUESTION: What to do here?
          *
          * According to 'man bind', the path that represents the 
address must
          * be unlink'ed. However, the path seems to be available only 
through
          * UnixAddress.path but UnixAddress is not available by default 
and it
          * is not convenient to use (e.g. it does not have a 
constructor that
          * takes the port value).
          */
     }
     // Wait for the client
     listener.listen(1);
     writeln("Waiting for the client");
     // Accept the connection
     Socket connection = listener.accept();
     scope (exit) {
         writefln("Shutting down and closing the client connection %s",
                  connection.remoteAddress());
         connection.shutdown(SocketShutdown.BOTH);
         connection.close();
     }
     ubyte[1000] buffer;
     bool isAllReceived = false;
     while (!isAllReceived) {
         const received = connection.receive(buffer);
         if (received == Socket.ERROR) {
             writeln("READ ERROR");
             break;
         } else {
             writefln("Received %s bytes; as string: %s",
                      received, cast(string)buffer[0..received]);
         }
         isAllReceived = (received < buffer.length);
     }
     if (isAllReceived) {
         enum header =
             "HTTP/1.0 200 OK\nContent-Type: text/html; charset=utf-8\n\n";
         string response = header ~ "Hello World!\n";
         connection.send(response);
     }
}
Thank you,
Ali
 Aug 26 2013
On Tuesday, 27 August 2013 at 03:30:11 UTC, Ali Çehreli wrote:It cannot be started a second time for 8080 still being in use, unless you wait for several secondsIt works on Windows7, no need to wait.
 Aug 26 2013
On Tue, 27 Aug 2013 04:30:10 +0100, Ali =C7ehreli <acehreli yahoo.com> w= rote:The following simple socket example is trying to cleanup after itself,==except the bind() call. As I repeat in the QUESTION comment below, I =have read the man page of bind and I know that I need to unlink a path=. =How can I get that path?That example is for AF_UNIX domain sockets. TcpSocket is an AF_INET = domain socket. In AF_INET there is no 'path' and there is nothing you = need to do to cleanup after bind - other than close the socket. I do no= t = believe a shutdown is required for a listening socket - tho don't quote = me = on that.The problem is, currently the program apparently leakes some resources=. =It cannot be started a second time for 8080 still being in use, unless==you wait for several seconds, presumably until the OS does the cleanup=. Correct. And this time varies by platform, as dnewbie mentions on Windo= ws = you can re-use immediately. You could set the REUSE option on the socket prior to 'bind', this would= = allow you to bind again while the previous socket was in cleanup. The other thing which might be affecting things is.. Take a look at: http://linux.die.net/man/7/socket Specifically "SO_LINGER". This socket option controls whether and how = long a socket will linger after it is closed. I am not sure what the = linux defaults are for that, but it may be set to linger intentionally. = = You could use getsockopt to obtain the LINGER default values and see. Also.. the sentence "When the socket is closed as part of exit(2), it = always lingers in the background." made me think, when does scope(exit) = = fire? Does it occur as part of exit in your example? Does manually = calling shutdown/close on the listening socket resolve the issue. Regan -- = Using Opera's revolutionary email client: http://www.opera.com/mail/
 Aug 27 2013
On 08/27/2013 02:02 AM, Regan Heath wrote:You could set the REUSE option on the socket prior to 'bind', this would allow you to bind again while the previous socket was in cleanup.That worked. I copied the following line from std/socket.d: listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true); Ali
 Aug 27 2013








 
  
  
 
 "dnewbie" <run3 myopera.com>
 "dnewbie" <run3 myopera.com> 