Thread overview
Socket and SocketStream
Apr 04, 2010
Kyle Mallory
Apr 06, 2010
Kyle Mallory
Apr 06, 2010
Jesse Phillips
Apr 06, 2010
Kyle Mallory
Apr 06, 2010
Kyle Mallory
April 04, 2010
I'm trying a bit of socket stuff.  I went back to the htmlget.d sample, and patched it up for 2.0 (I'm using DMD 2.042 on Ubuntu 9.10).  I get the same results from this as I do from my own code, which is that writeString() on the SocketStream throws an exception.

From everything I can tell, I don't have an established connection, even though everything claims I have one.

Here is the updated sample code:

/*
	HTMLget written by Christopher E. Miller
	This code is public domain.
	You may use it for any purpose.
	This code has no warranties and is provided 'as-is'.
*/


//debug = HTMLGET;


module htmlget;
import std.string, std.conv, std.stream;
import std.socket, std.socketstream;
import std.stdio;

int main(string[] args)
{
	uint addr;
	if(args.length < 2)
	{
		printf("Usage:\n   htmlget <web-page>\n");
		return 0;
	}
	string url = args[1];
	int i;

	//i = std.string.find(url, "://");
	i=std.string.indexOf(url,"://");
	if(i != -1)
	{
		if(icmp(url[0 .. i], "http"))
			throw new Exception("http:// expected");
	}

	url = url[i+3 .. url.length];

	//i = std.string.find(url, '#');
	i=std.string.indexOf(url,'#');
	if(i != -1) // Remove anchor ref.
		url = url[0 .. i];

	//i = std.string.find(url, '/');
	i=std.string.indexOf(url,'/');
	string domain;
	if(i == -1)
	{
		domain = url;
		url = "/";
	}
	else
	{
		domain = url[0 .. i];
		url = url[i .. url.length];
	}

	ushort port;
	//i = std.string.find(domain, ':');
	i = std.string.indexOf(domain,':');
	if(i == -1)
	{
		port = 80; // Default HTTP port.
	}
	else
	{
		port=parse!(ushort)(domain[i+1..domain.length]);
		domain = domain[0 .. i];
	}

	writefln("Parsed domain: %s, port: %d and url: %s", domain, port, url);

	addr = InternetAddress.parse(domain);
	debug(HTMLGET)
		writefln("Connecting to %s on port %d...", domain, port);

	auto Socket sock = new TcpSocket(new std.socket.InternetAddress(addr/*domain*/, port));
	Stream ss = new SocketStream(sock);

	debug(HTMLGET)
		printf("Connected!\nRequesting URL \"" ~ url ~ "\"...\n");

	if(port != 80)
	{
		char[] temp=cast(char[]) domain;
		temp=temp~cast(char[])":" ~cast(char[]) (to!string(port));
		domain=cast(string)temp;
	}
	ss.writeString("GET " ~ url ~ " HTTP/1.1\r\n"
		"Host: " ~ domain ~ "\r\n"
		"\r\n");

	// Skip HTTP header.
	string line;
	for(;;)
	{
		line = cast(string)ss.readLine();
		if(!line.length)
			break;

		const string CONTENT_TYPE_NAME = "Content-Type: ";
		if(line.length > CONTENT_TYPE_NAME.length &&
			!icmp(CONTENT_TYPE_NAME, line[0 .. CONTENT_TYPE_NAME.length]))
		{
			string type;
			type = line[CONTENT_TYPE_NAME.length .. line.length];
			if(type.length <= 5 || icmp("text/", type[0 .. 5]))
				throw new Exception("URL is not text");
		}
	}

	print_lines:
	while(!ss.eof())
	{
		line = cast(string)ss.readLine();
		printf("%.*s\n", line);

		size_t iw;
		for(iw = 0; iw != line.length; iw++)
		{
			if(!icmp("</html>", line[iw .. line.length]))
				break print_lines;
		}
	}

	return 0;
}


And here is my invocation, and its response:

$ dmd -run ./htmlget2.d http://10.120.1.106:80/
Parsed domain: 10.120.1.106, port: 80 and url: /
std.stream.WriteException: unable to write to stream
$


Can anyone else duplicate this?  Or let me know if I'm doing something wrong in my updating of the sample code?


April 06, 2010
I hate replying to my own thead.  :-(

I was able to compile listener.d, and connect successfully to it via telnet., so I know at least the listener stuff so working.

However, stepping down to an even simpler example, I can't even get the following code to establish a connection:


import std.socket;

void main(string[] args) {

	Socket s = new TcpSocket(new InternetAddress(args[1], parse!(ushort)(args[2])));
	assert(s.isAlive);
	s.close();
}


Connecting against listener.d, I should at least see a "connection from" and a "disconnected".  But nothing happens.  No error messages, no exceptions, etc.

Am I the only one with this problem?





On 04/04/2010 11:36 AM, Kyle Mallory wrote:
> I'm trying a bit of socket stuff.  I went back to the htmlget.d sample,
> and patched it up for 2.0 (I'm using DMD 2.042 on Ubuntu 9.10). I get
> the same results from this as I do from my own code, which is that
> writeString() on the SocketStream throws an exception.
>
>  From everything I can tell, I don't have an established connection,
> even though everything claims I have one.
>
> Here is the updated sample code:
>
> /*
> HTMLget written by Christopher E. Miller
> This code is public domain.
> You may use it for any purpose.
> This code has no warranties and is provided 'as-is'.
> */
>
>
> //debug = HTMLGET;
>
>
> module htmlget;
> import std.string, std.conv, std.stream;
> import std.socket, std.socketstream;
> import std.stdio;
>
> int main(string[] args)
> {
> uint addr;
> if(args.length < 2)
> {
> printf("Usage:\n htmlget <web-page>\n");
> return 0;
> }
> string url = args[1];
> int i;
>
> //i = std.string.find(url, "://");
> i=std.string.indexOf(url,"://");
> if(i != -1)
> {
> if(icmp(url[0 .. i], "http"))
> throw new Exception("http:// expected");
> }
>
> url = url[i+3 .. url.length];
>
> //i = std.string.find(url, '#');
> i=std.string.indexOf(url,'#');
> if(i != -1) // Remove anchor ref.
> url = url[0 .. i];
>
> //i = std.string.find(url, '/');
> i=std.string.indexOf(url,'/');
> string domain;
> if(i == -1)
> {
> domain = url;
> url = "/";
> }
> else
> {
> domain = url[0 .. i];
> url = url[i .. url.length];
> }
>
> ushort port;
> //i = std.string.find(domain, ':');
> i = std.string.indexOf(domain,':');
> if(i == -1)
> {
> port = 80; // Default HTTP port.
> }
> else
> {
> port=parse!(ushort)(domain[i+1..domain.length]);
> domain = domain[0 .. i];
> }
>
> writefln("Parsed domain: %s, port: %d and url: %s", domain, port, url);
>
> addr = InternetAddress.parse(domain);
> debug(HTMLGET)
> writefln("Connecting to %s on port %d...", domain, port);
>
> auto Socket sock = new TcpSocket(new
> std.socket.InternetAddress(addr/*domain*/, port));
> Stream ss = new SocketStream(sock);
>
> debug(HTMLGET)
> printf("Connected!\nRequesting URL \"" ~ url ~ "\"...\n");
>
> if(port != 80)
> {
> char[] temp=cast(char[]) domain;
> temp=temp~cast(char[])":" ~cast(char[]) (to!string(port));
> domain=cast(string)temp;
> }
> ss.writeString("GET " ~ url ~ " HTTP/1.1\r\n"
> "Host: " ~ domain ~ "\r\n"
> "\r\n");
>
> // Skip HTTP header.
> string line;
> for(;;)
> {
> line = cast(string)ss.readLine();
> if(!line.length)
> break;
>
> const string CONTENT_TYPE_NAME = "Content-Type: ";
> if(line.length > CONTENT_TYPE_NAME.length &&
> !icmp(CONTENT_TYPE_NAME, line[0 .. CONTENT_TYPE_NAME.length]))
> {
> string type;
> type = line[CONTENT_TYPE_NAME.length .. line.length];
> if(type.length <= 5 || icmp("text/", type[0 .. 5]))
> throw new Exception("URL is not text");
> }
> }
>
> print_lines:
> while(!ss.eof())
> {
> line = cast(string)ss.readLine();
> printf("%.*s\n", line);
>
> size_t iw;
> for(iw = 0; iw != line.length; iw++)
> {
> if(!icmp("</html>", line[iw .. line.length]))
> break print_lines;
> }
> }
>
> return 0;
> }
>
>
> And here is my invocation, and its response:
>
> $ dmd -run ./htmlget2.d http://10.120.1.106:80/
> Parsed domain: 10.120.1.106, port: 80 and url: /
> std.stream.WriteException: unable to write to stream
> $
>
>
> Can anyone else duplicate this? Or let me know if I'm doing something
> wrong in my updating of the sample code?
>
>

April 06, 2010
I believe you are running into this bug:

http://d.puremagic.com/issues/show_bug.cgi?id=2835

Where sockets don't work in Linux.
April 06, 2010
On 04/05/2010 06:56 PM, Jesse Phillips wrote:
> I believe you are running into this bug:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=2835
>
> Where sockets don't work in Linux.


Argh.. Thanks.  Looks like an easy enough patch.  Unfortunate the bug its still lingering in the latest build (especially considering that a patch is provided).

I guess the next step is figuring out how to rebuild the phobos library.

Thanks.
April 06, 2010
On 04/05/2010 06:56 PM, Jesse Phillips wrote:
> I believe you are running into this bug:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=2835
>
> Where sockets don't work in Linux.

Thank you, Jesse!  Applied the patch, recompiled libdruntime.a and libphobos2.a and everything is working as expected!

Very much appreciated!

Kyle