Matthias Hoste
Matthias Hoste

Reputation: 125

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

Upvotes: 0

Views: 115

Answers (1)

Avner Shahar-Kashtan
Avner Shahar-Kashtan

Reputation: 14700

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)

Upvotes: 1

Related Questions