How to cleanup after Socket.bind on Linux?

Ali Çehreli acehreli at yahoo.com
Mon Aug 26 20:30:10 PDT 2013


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


More information about the Digitalmars-d-learn mailing list