Note that there are some explanatory texts on larger screens.

plurals
  1. POTcpClient read OutOfMemoryException
    primarykey
    data
    text
    <p>I have problem with <strong>intermittent OutOfMemoryException</strong>, on the line </p> <blockquote> <p>buffer = new byte[metaDataSize];</p> </blockquote> <p><em>(Under //Read the command's Meta data.)</em></p> <p>Does this mean I try to read the complete message while only part of it has been received? In case, what is a reliable way to handle that? Btw, I need variable length messages, as most are very short, while occasional messages are very large. Should I attach the complete message size in front of the message? Still, how can I know how much the stream contains before trying to read from it? (as it seems the read sometimes fails when trying to read a specific length, like I currently do) </p> <pre><code> public static Command Read(NetworkStream ns) { try { //Read the command's Type. byte[] buffer = new byte[4]; int readBytes = ns.Read(buffer, 0, 4); if (readBytes == 0) return null; CommandType cmdType = (CommandType)(BitConverter.ToInt32(buffer, 0)); //Read cmdID buffer = new byte[4]; readBytes = ns.Read(buffer, 0, 4); if (readBytes == 0) return null; int cmdID = BitConverter.ToInt32(buffer, 0); //Read MetaDataType buffer = new byte[4]; readBytes = ns.Read(buffer, 0, 4); if (readBytes == 0) return null; var metaType = (MetaTypeEnum)(BitConverter.ToInt32(buffer, 0)); //Read the command's MetaData size. buffer = new byte[4]; readBytes = ns.Read(buffer, 0, 4); if (readBytes == 0) return null; int metaDataSize = BitConverter.ToInt32(buffer, 0); //Read the command's Meta data. object cmdMetaData = null; if (metaDataSize &gt; 0) { buffer = new byte[metaDataSize]; int read = 0, offset = 0, toRead = metaDataSize; //While while (toRead &gt; 0 &amp;&amp; (read = ns.Read(buffer, offset, toRead)) &gt; 0) { toRead -= read; offset += read; } if (toRead &gt; 0) throw new EndOfStreamException(); // readBytes = ns.Read(buffer, 0, metaDataSize); //if (readBytes == 0) // return null; // readBytes should be metaDataSize, should we check? BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(buffer); ms.Position = 0; cmdMetaData = bf.Deserialize(ms); ms.Close(); } //Build and return Command Command cmd = new Command(cmdType, cmdID, metaType, cmdMetaData); return cmd; } catch (Exception) { throw; } } </code></pre> <p>WRITE method: </p> <pre><code> public static void Write(NetworkStream ns, Command cmd) { try { if (!ns.CanWrite) return; //Type [4] // Type is an enum, of fixed 4 byte length. So we can just write it. byte[] buffer = new byte[4]; buffer = BitConverter.GetBytes((int)cmd.CommandType); ns.Write(buffer, 0, 4); ns.Flush(); // Write CmdID, fixed length [4] buffer = new byte[4]; // using same buffer buffer = BitConverter.GetBytes(cmd.CmdID); ns.Write(buffer, 0, 4); ns.Flush(); //MetaDataType [4] buffer = new byte[4]; buffer = BitConverter.GetBytes((int)cmd.MetaDataType); ns.Write(buffer, 0, 4); ns.Flush(); //MetaData (object) [4,len] if (cmd.MetaData != null) { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, cmd.MetaData); ms.Seek(0, SeekOrigin.Begin); byte[] metaBuffer = ms.ToArray(); ms.Close(); buffer = new byte[4]; buffer = BitConverter.GetBytes(metaBuffer.Length); ns.Write(buffer, 0, 4); ns.Flush(); ns.Write(metaBuffer, 0, metaBuffer.Length); ns.Flush(); if (cmd.MetaDataType != MetaTypeEnum.s_Tick) Console.WriteLine(cmd.MetaDataType.ToString() + " Meta: " + metaBuffer.Length); } else { //Write 0 length MetaDataSize buffer = new byte[4]; buffer = BitConverter.GetBytes(0); ns.Write(buffer, 0, 4); ns.Flush(); } } catch (Exception) { throw; } } </code></pre> <p>VB.NET:</p> <pre><code>Private tcp As New TcpClient Private messenger As InMessenger Private ns As NetworkStream Public Sub New(ByVal messenger As InMessenger) Me.messenger = messenger End Sub Public Sub Connect(ByVal ip As String, ByVal port As Integer) Try tcp = New TcpClient Debug.Print("Connecting to " &amp; ip &amp; " " &amp; port) 'Connect with a 5sec timeout Dim res = tcp.BeginConnect(ip, port, Nothing, Nothing) Dim success = res.AsyncWaitHandle.WaitOne(5000, True) If Not success Then tcp.Close() Else If tcp.Connected Then ns = New NetworkStream(tcp.Client) Dim bw As New System.ComponentModel.BackgroundWorker AddHandler bw.DoWork, AddressOf DoRead bw.RunWorkerAsync() End If End If Catch ex As Exception Trac.Exception("Connection Attempt Exception", ex.ToString) CloseConnection() End Try End Sub Private Sub DoRead() Try While Me.tcp.Connected ' read continuously : Dim cmd = CommandCoder.Read(ns) If cmd IsNot Nothing Then HandleCommand(cmd) Else Trac.TraceError("Socket.DoRead", "cmd is Nothing") CloseConnection() Exit While End If If tcp.Client Is Nothing Then Trac.TraceError("Socket.DoRead", "tcp.client = nothing") Exit While End If End While Catch ex As Exception Trac.Exception("Socket.DoRead Exception", ex.ToString()) CloseConnection() EventBus.RaiseErrorDisconnect() End Try End Sub </code></pre> <hr> <p><strong>EDIT:</strong></p> <p>I put in some WriteLine's, and found that some packages sent are recognized with wrong size on receiver side. So the metaDataSize which should be 9544 for a certain message, is read as 5439488, or similar incorrect value. I <em>assume</em> on few occations this number is so large it causes the OutOfMemoryException.</p> <p>Seems Douglas' answer may be on the mark(?), I will test. For info: The server (sender) program is built as "Any CPU", ran on Windows 7 x64 pc. While the Client (receiver) is built as x86, and (during this test) ran on XP. But must also be coded to work on other windows x86 or x64. </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload