【问题标题】:OutOfMemoryException when server reads message from client当服务器从客户端读取消息时出现 OutOfMemoryException
【发布时间】:2016-09-11 11:16:57
【问题描述】:

我正在制作一个客户端-服务器应用程序,但是当我尝试登录时它会引发 OutOfMemoryException,这是我的服务器端代码:

                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();

这是我的客户端代码:

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();

所以基本上客户端首先将实际消息的长度发送到服务器,以便它知道它需要多少字节,但是当我创建一个新的缓冲区来保存消息时,它会抛出 OutOfMemoryException,

提前致谢

【问题讨论】:

  • MessageSize 的评估结果是什么?您确定您的标头嗅探得出了正确的值吗?看起来您正在读取前 4 个字节两次,这可能意味着您实际上是在将缓冲区大小基于第 5-8 个字节。
  • 此外,您正在使用 BitConverter 来读取数字。您确定您正确读取了这些位吗?有线格式是否可能使用与您预期不同的字节序?
  • MessageSize 保存正在接收的消息的实际大小
  • 既然你提出来了,嗯,等一下,看看它在运行时读取的字节数
  • 是的,在运行时。检查实际读取了什么,而不是假定会发生什么。

标签: c#


【解决方案1】:

问题可能在于您如何读取包含消息长度的标头:

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

您在这里所做的是将流中的 4 个字节读取到缓冲区中,然后再次读取 4 个字节,覆盖之前的缓冲区。这与您在下面的客户端发送代码不匹配,其中标头在前 4 个字节中发送。所以发生的情况是,您获取消息大小,用实际有效负载的前 4 个字节覆盖它,然后尝试根据这 4 个任意字节分配缓冲区。

删除第二个 Read 调用,应该没问题。

不过,一般来说,您正在做框架已经可以为您完成的大量工作。您可以创建一个StreamWriter 来为您管理所有阅读,而无需将消息大小作为“标题”发送:

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

(当然还有对应的StreamWriter调用)

【讨论】:

  • 像魅力一样工作,谢谢 :) 它之前有另一个功能,需要读取另一个长度,我忘了删除第二个阅读器,非常愚蠢的错误,但非常感谢 :)
猜你喜欢
  • 2016-03-18
  • 2015-10-08
  • 1970-01-01
  • 2017-04-30
  • 2013-03-02
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多