Matthias Hoste Matthias Hoste - 2 months ago 29
C# Question

OutOfMemoryException when server reads message from client

I'm making a client-server application, but when I try to login it throws an OutOfMemoryException, here is my code server-side:

byte[] buffer = new byte[4];
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
buffer = new byte[4];
int readBytes = networkStream.Read(buffer, 0, 4);
readBytes = networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int MessageSize = BitConverter.ToInt32(buffer, 0);
byte[] bufferreader = new byte[MessageSize]; <- here the exception is thrown
readBytes = networkStream.Read(bufferreader, 0, MessageSize);
if (readBytes == 0)
break;
dataFromClient = Encoding.ASCII.GetString(bufferreader);
rCount = Convert.ToString(requestCount);
serverResponse = R.Respond(dataFromClient);
sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();


and here is my client-side code:

clientSocket.Connect("192.168.1.100", 666);
SHA512Managed S = new SHA512Managed();
byte[] result = S.ComputeHash(Encoding.UTF8.GetBytes(password));
string epassword = Convert.ToBase64String(result);
try
{
byte[] buffer = new byte[4];
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = Encoding.ASCII.GetBytes("authenticate|" + user + "$");
buffer = new byte[4];
buffer = BitConverter.GetBytes(outStream.Length);
serverStream.Write(buffer, 0, 4);
serverStream.Flush();
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
string returndata = Encoding.ASCII.GetString(inStream);
}
catch(Exception ex)
{
Toast.MakeText(l, ex.Message, ToastLength.Long).Show();
}
Toast.MakeText(l, "Logged In: " + epassword, ToastLength.Long).Show();


So basically the client first sends the length of the actual message to the server so it knows how much bytes it has to expect, but when i create a new buffer that will hold the message it throws the OutOfMemoryException,

Thanks in advance

Answer

The problem probably lies in how you read the header containing the message length:

buffer = new byte[4];
int readBytes = networkStream.Read(buffer, 0, 4);
readBytes = networkStream.Read(buffer, 0, 4);

What you're doing here is reading 4 bytes off the stream into a buffer, and then reading 4 bytes again, overriding the previous buffer. This doesn't match the client sending code you have below, where the header is sent in the first 4 bytes. So what happens is that you get the message size, override it with the first 4 bytes of the actual payload, and then try to allocate a buffer based on those 4 arbitrary bytes.

Remove the second Read call, and it should be fine.

Generally speaking, though, you're doing a lot of work that the framework can already do for you. You can create a StreamWriter to manage all your reads for you, without bothering with sending the message size as a "header":

NetworkStream networkStream = clientSocket.GetStream();
StreamReader reader = new StreamReader(networkStream, Encoding.ASCII)
dataFromClient =  reader.ReadToEnd();

(And the corresponding StreamWriter calls, of course)