View mode: basic / threaded / horizontal-split · Log in · Help
April 28, 2005
Problem with SocketStream.readLine
Hi,

could please somebody explain me why the following code doesn't work properly?

It was tested on Windows ME, so you have to link with ws2_32.lib to compile it.

The code starts 2 threads, a server and a client which communicate by a TCP 
socket. The client sends a single line (ending with "\r\n") as a request to the 
server, the server reads it and responds with exactly 100000 bytes of data, but 
the client receives only a part of the data.

Curiously, the code works perfectly well if the request string only ends with 
"\n".

After I replaced SocketStream.readLine() with a slightly modified function which 
ignores "\r" characters, it worked also.

Thanks in advance


Michael




The code:
--------------------------------------------------

import std.socket;
import std.socketstream;
import std.stream;
import std.thread;


const char[] IP = "127.0.0.1";      // Address to use for connection
const int PORT = 2000;              // Port to use     
const int TESTLENGTH = 100000;      // Length of test data
const ubyte[TESTLENGTH] testbuffer; // Data to send from server to client



// Request string to send from client to server:

const char[] REQSTRING = "Testing\r\n";   // Does not work
// const char[] REQSTRING = "Testing\n";  // Works  (Missing '\r')




int serve()  // Server function
{
 auto Socket listener = new TcpSocket();
 listener.bind(new InternetAddress(IP, PORT));
 listener.listen(10);

 Socket sock;

 while (true)
 {
   try
   {
     sock = listener.accept();
     printf("Request\n");

     sock.blocking = true;

     SocketStream stream = new SocketStream(sock);

     stream.readLine();   // Read request

     int sent = stream.write(testbuffer);  // Send data
     
     sock.shutdown(SocketShutdown.BOTH);
     sock.close();
     printf("Sent: %i\n", sent);
   }
   catch (Exception exc)
   {
     printf("Server Error\n");
     exc.print();
   }
 }
}


void request()  // Client function
{
 while(true)
 {
   int i = 0;
   try
   {
     Socket sock = new TcpSocket(new InternetAddress(IP, PORT));
     SocketStream stream = new SocketStream(sock);

     char buffer;

     stream.write(cast(ubyte[])REQSTRING);  // Send request

     while(true)
     {
       stream.read(buffer);  // Read data
       ++i;
     }
   }
   catch (Exception exc)
   {
     printf("Read: %i\n", i);
   }
 }
}



int main(char[][] args)
{
 int runreq()
 {
   request();
   return 0;
 }

 int runserv()
 {
   serve();
   return 0;
 }

 Thread t;
 if (args.length == 1 || args[1] == "s")  // Server only
 {
   t = new Thread(&runserv);
   t.start();
 }

 if (args.length == 1 || args[1] == "c")  // Client only
 {
   t = new Thread(&runreq);
   t.start();
 }

 t.wait();

 return 0;
}


--------------------------------------------------
April 28, 2005
Re: Problem with SocketStream.readLine
Interesting. I don't know much about sockets but the socketstream.readline 
doesn't read the last \n when it sees the \r - it leaves it in the stream 
until the next read. I assume that's because readLine doesn't actually know 
if there is a \n coming and it doesn't want to block waiting for one. It 
seems, though, that leaving that char in the stream gets in the way of 
future send/recv calls. It doesn't matter what that last char is or if it 
just reads an incomplete amount of data. Is there a way to know if the line 
ending is \r or \r\n ahead of time or is there some setting on the socket 
that will fix it? Again I don't know the details of how sockets send and 
recieve so someone else besides me will have to help out (I generally take 
generic stream questions but this one seems out of my realm).

"Michael Butscher" <mbutscher@gmx.de> wrote in message 
news:MPG.1cdb6332bdc3cce0989681@news.digitalmars.com...
> Hi,
>
> could please somebody explain me why the following code doesn't work 
> properly?
>
> It was tested on Windows ME, so you have to link with ws2_32.lib to 
> compile it.
>
> The code starts 2 threads, a server and a client which communicate by a 
> TCP
> socket. The client sends a single line (ending with "\r\n") as a request 
> to the
> server, the server reads it and responds with exactly 100000 bytes of 
> data, but
> the client receives only a part of the data.
>
> Curiously, the code works perfectly well if the request string only ends 
> with
> "\n".
>
> After I replaced SocketStream.readLine() with a slightly modified function 
> which
> ignores "\r" characters, it worked also.
>
> Thanks in advance
>
>
> Michael
April 29, 2005
Re: Problem with SocketStream.readLine
Hmm, win32 and linux both use \n as the 'last' char to denote a new line,
probably should use this ?

Charlie
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message
news:d4rt0d$229n$1@digitaldaemon.com...
> Interesting. I don't know much about sockets but the socketstream.readline
> doesn't read the last \n when it sees the \r - it leaves it in the stream
> until the next read. I assume that's because readLine doesn't actually
know
> if there is a \n coming and it doesn't want to block waiting for one. It
> seems, though, that leaving that char in the stream gets in the way of
> future send/recv calls. It doesn't matter what that last char is or if it
> just reads an incomplete amount of data. Is there a way to know if the
line
> ending is \r or \r\n ahead of time or is there some setting on the socket
> that will fix it? Again I don't know the details of how sockets send and
> recieve so someone else besides me will have to help out (I generally take
> generic stream questions but this one seems out of my realm).
>
> "Michael Butscher" <mbutscher@gmx.de> wrote in message
> news:MPG.1cdb6332bdc3cce0989681@news.digitalmars.com...
> > Hi,
> >
> > could please somebody explain me why the following code doesn't work
> > properly?
> >
> > It was tested on Windows ME, so you have to link with ws2_32.lib to
> > compile it.
> >
> > The code starts 2 threads, a server and a client which communicate by a
> > TCP
> > socket. The client sends a single line (ending with "\r\n") as a request
> > to the
> > server, the server reads it and responds with exactly 100000 bytes of
> > data, but
> > the client receives only a part of the data.
> >
> > Curiously, the code works perfectly well if the request string only ends
> > with
> > "\n".
> >
> > After I replaced SocketStream.readLine() with a slightly modified
function
> > which
> > ignores "\r" characters, it worked also.
> >
> > Thanks in advance
> >
> >
> > Michael
>
>
April 29, 2005
Re: Problem with SocketStream.readLine
"Charlie" <charles@jwavro.com> wrote in message 
news:d4rtoi$2309$1@digitaldaemon.com...
> Hmm, win32 and linux both use \n as the 'last' char to denote a new line,
> probably should use this ?

The trouble is that mac line endings might be coming down the stream and you 
don't know before-hand. Just because the code reading the stream is on win32 
or linux doesn't mean the code that wrote to the stream is using that 
platform's line endings.

The general Stream class does a getc when it sees a \r to scarf up any 
following \n and it has always bothered me that the getc might block as it 
waits for the next char. Maybe the right thing to do is put some "peeking" 
code into streamsocket that scarfs up the \n if it is available. Does anyone 
know if the \n will always be peekable if one is there?
April 29, 2005
Re: Problem with SocketStream.readLine
On Thu, 28 Apr 2005 16:17:15 -0400, Michael Butscher <mbutscher@gmx.de>  
wrote:

> Hi,
>
> could please somebody explain me why the following code doesn't work  
> properly?
>

While I was running your code I noticed the client will start working  
correctly if the console has focus for awhile and/or if you hit enter or  
move the mouse over it. I even rewrote it to not use the SocketStream and  
still ran into read problems on the client side. I'll mess around with it  
some more.
- Chris
April 29, 2005
Re: Problem with SocketStream.readLine
Vathix wrote:

> While I was running your code I noticed the client will start working  
> correctly if the console has focus for awhile and/or if you hit enter or  
> move the mouse over it. I even rewrote it to not use the SocketStream and  
> still ran into read problems on the client side. I'll mess around with it  
> some more.


It seems that it works (at least better), if the server pauses a bit between 
sending data and closing the socket (e. g. by a dummy for-loop)

Michael
Top | Discussion index | About this forum | D home