digitalmars.D.learn - Socket and SocketStream
- Kyle Mallory (121/121) Apr 04 2010 I'm trying a bit of socket stuff. I went back to the htmlget.d sample,
- Kyle Mallory (17/138) Apr 05 2010 I hate replying to my own thead. :-(
- Jesse Phillips (3/3) Apr 05 2010 I believe you are running into this bug:
- Kyle Mallory (6/9) Apr 05 2010 Argh.. Thanks. Looks like an easy enough patch. Unfortunate the bug
- Kyle Mallory (5/8) Apr 05 2010 Thank you, Jesse! Applied the patch, recompiled libdruntime.a and
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
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
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
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
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









Kyle Mallory <jesuswasirish gmail.com> 