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> 