Saturday, 24 August 2013

Socket buffers the data it receives

Socket buffers the data it receives

I have a client and a server, both .NET applications, connected through
sockets.
The client sends a string of 20 or so characters every 500 milliseconds.
On my local development machine, this works perfectly, but once the client
and the server are on two different servers, the server is not receiving
the string immediately when it's sent. The client still seems to be
sending perfectly, but the server only actually receives the message every
10 seconds or so - and then it receives all the content from those 10
seconds.
So it sounds very much like the receive socket is buffering the data. I
based the code on an example from Microsoft.
In AcceptCallback it establishes the connection and call BeginReceive
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new
AsyncCallback(ReadCallback), state);
This part works great. The BufferSize was 1024 in the beginning. I also
tried setting it to 10. It makes a difference in how much data it will
read from the socket at one time, but that's not really the problem. Once
it starts reading, it works fine.
I've put the ReadCallback method below. This also works well WHEN it is
invoked.
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0,
bytesRead));
// Check for end-of-file tag. If it is not there, read more data.
if (state.sb[state.sb.Length - 1] == '#')
{
// Code that gets and uses the string content
// Clear the state, to prepare for a fresh result
state.sb.Clear();
state.buffer = new byte[StateObject.BufferSize];
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
Once the ReadCallback is invoked, everything works fine. It will get all
of the data in the socket, perhaps 200 characters or so. If I set the
buffer to 10, it will run through 20 times immediately and get it all. So
it looks to be working very well.
This tells me the problem is somewhere else, perhaps in some setting on
the socket?

No comments:

Post a Comment