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