www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Socket and SocketStream

reply Kyle Mallory <jesuswasirish gmail.com> writes:
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];



	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?
Apr 04 2010
next sibling parent Kyle Mallory <jesuswasirish gmail.com> writes:
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];



 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?
Apr 05 2010
prev sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
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.
Apr 05 2010
next sibling parent Kyle Mallory <jesuswasirish gmail.com> writes:
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.
Apr 05 2010
prev sibling parent Kyle Mallory <jesuswasirish gmail.com> writes:
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
Apr 05 2010