TcpClient Socket Blocking Problems

  • Thread starter Christopher H. Laco
  • Start date
C

Christopher H. Laco

I'm having a problem with the TcpClient that I can only conclude is
either a feature, or a complete misunderstanding of the docs on my part.

In a nutshell, I'm simply performing the following sequence with a server:

connect
write(50 bytes)
read(2002 bytes)
write(50 bytes)
read(2002 bytes)
write(50 bytes)
read(2002 bytes)
disconnect

At random times, one of the read sequences will read only 1460 bytes
instead of 2002 bytes. The reaminder, 542 bytes, just happens to fall on
a packet boundry. More on that later.

Now, for the sake of this argument, the number of times the write/read
sequence could happen per connection is unknown. Could be once; could be
20 times.

Now for some somewhat real code...

TcpClient client = new TcpClient();


client.NoDelay = true;
client.Client.Blocking = true;
client.Connect("remote_server", 3456);

for (int i = 1; i++; i <= 3) {
Byte[] outputbuffer;
NetworkStream stream;

outputbuffer = Encoding.ASCII.GetBytes("50 bytes of data...");
stream = this.GetStream();
stream.Write(outputbuffer, 0, outputbuffer.Length);

Byte[] inputbuffer;
inputbuffer = new Byte[2002];
Debug.WriteLine(stream.Read(inputbuffer, 0,inputbuffer.Length));
}


client.Close();


Now, sometimes when I run this, I get:
2002
2002
1460
Or this:
1460
2002
2002
OR this:
2002
1460
2002

Clearly, Socket.Blocking is not doing what I expect.
Sockst docs say that BLocking is on by default, so shouldn't it be doing
so, or is this a matter of the NetworkStream not doing something right?

Should I be using the Socket.Send/Receive methods instead?

At this point, I'm quite confused about the interaction of Socket vs.
NetworkStream within the TcpClient.

Thanks,
-=Chris
 
C

Christopher H. Laco

Christopher H. Laco wrote:
[snip]
Now, sometimes when I run this, I get:
2002
2002
1460
Or this:
1460
2002
2002
OR this:
2002
1460
2002

I forgot the mention that in the cases where NetworkSteam.Read returns
1460 instead of the requested 2002, the full 2002 bytes have indeed been
sent by the server and seen by the network card as witnessed by a good
dose of Ethereal packet sniffing.

In those cases, the 1460 is the first of two packets, and the second
packet contains the remaining 542 bytes of data.

-=Chris
 
S

Sunny

Hi,

stream.Read does not obey that all data will be received. You have to
loop Read untill it returns 0.

Try something like this:

byte[] buffer = new byte[2002];
int bytesread = 0;

while (stream.Read(buffer, bytesread, buffer.Length - bytesread) > 0);

Note, I haven't tested this exact code, but it should work, or at least
it shows you the idea.

Sunny

Christopher H. Laco wrote:
[snip]
Now, sometimes when I run this, I get:
2002
2002
1460
Or this:
1460
2002
2002
OR this:
2002
1460
2002

I forgot the mention that in the cases where NetworkSteam.Read returns
1460 instead of the requested 2002, the full 2002 bytes have indeed been
sent by the server and seen by the network card as witnessed by a good
dose of Ethereal packet sniffing.

In those cases, the 1460 is the first of two packets, and the second
packet contains the remaining 542 bytes of data.

-=Chris
 
C

Christopher H. Laco

Sunny said:
Hi,

stream.Read does not obey that all data will be received. You have to
loop Read untill it returns 0.

Try something like this:

byte[] buffer = new byte[2002];
int bytesread = 0;

while (stream.Read(buffer, bytesread, buffer.Length - bytesread) > 0);

Note, I haven't tested this exact code, but it should work, or at least
it shows you the idea.

Sunny

Yeah, I knew about the loop trick. There seems to be some dissention
about whether to loop on DataAvailable or on the int count returned from
Read. Although, I'd think the latter is safer.

I guess I'm more curious as to WHY the NetworkStream doesn't really
honor socket blocking in the sence of waiting until I have all the bytes
requested.

-=Chris
 
S

Sunny

Hi,

I guess I'm more curious as to WHY the NetworkStream doesn't really
honor socket blocking in the sence of waiting until I have all the bytes
requested.

-=Chris

Because the network streem does not support Length property. So there is
no way to query it about the content. You just read until it ends.

in very basic terms:
The socket is the communication part only. The stream is the content.
The socket only provides access to the stream, it does not deal with its
content. So it blocks only until there is some stream, and after that if
passes that stream to you for reading.

Sunny
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top