2014-05-09 58 views
1

这是一种情况:我正在建立一个TCP连接(对我自己)以字符串格式发送一些数据。我创建一个连接,我发送数据,并立即关闭连接(我不想等待数据同步)。在发送字符串之前,我在字符串的前面附加了它的长度(data.Length),所以我知道接收时要读取多少数据。 我有一个StreamSocketListener监听来自TCP连接的传入数据,我做了一些“助手”类来简化外部世界的内容。该类实例化一次,并调用方法Start开始监听连接。这是场景。 当我发送数据(对我自己,但这不应该),我得到System.OutOfMemoryException在方法StreamReadLine从DataReader读取数据时发生OutOfMemoryException

这对我来说不是很明显,为什么会发生这种情况,所以这就是我来到这里的原因。我希望以前有人处理过这个问题,并且知道问题是什么。

public delegate void TCPRequestHandler(string data, string sender); 
public class TCPSocketListener 
{ 
    private int port; 
    private StreamSocketListener listener; 
    private bool mIsActive = false; 
    private event TCPRequestHandler requestHandlerCallback; 

    public bool isActive 
    { 
     get { return mIsActive; } 
    } 

    public TCPSocketListener(int port, TCPRequestHandler requestHandlerCallback) 
    { 
     this.port = port; 
     this.requestHandlerCallback = requestHandlerCallback; 
    } 

    public async void Start() 
    { 
     if (!mIsActive) 
     { 
      mIsActive = true; 
      listener = new StreamSocketListener(); 
      listener.Control.QualityOfService = SocketQualityOfService.Normal; 
      listener.ConnectionReceived += Listener_ConnectionReceived; 
      await listener.BindServiceNameAsync(port.ToString()); 
     } 
    } 

    public void Stop() 
    { 
     if (mIsActive) 
     { 
      listener.Dispose(); 
      mIsActive = false; 
     } 
    } 

    async void Listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) 
    { 
     string data = await ExtractRequestData(args.Socket); 
     await Task.Run(() => requestHandlerCallback(data, args.Socket.Information.RemoteHostName.CanonicalName)); 
    } 

    private async Task<string> ExtractRequestData(StreamSocket socket) 
    { 
     //Initialize IO classes 
     DataReader reader = new DataReader(socket.InputStream); 
     //DataWriter writer = new DataWriter(socket.OutputStream); 
     //writer.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8; 

     // get the data on the stream 
     string data = await StreamReadLine(reader); 

     socket.Dispose(); 
     return data; 
    } 

    private static async Task<string> StreamReadLine(DataReader reader) 
    { 
     System.Diagnostics.Debug.WriteLine("reading data"); 
     var stringHeader = await reader.LoadAsync(4); 

     if (stringHeader == 0) 
     { 
      System.Diagnostics.Debug.WriteLine("Header of the data was 0, for whatever reason"); 
      return "null"; 
     } 
     int strLength = reader.ReadInt32(); 
     uint numStrBytes = await reader.LoadAsync((uint)strLength); 
     string data = reader.ReadString(numStrBytes); 
     System.Diagnostics.Debug.WriteLine("read " + data); 
     return data; 
    } 
} 
+2

你调试的代码并确认您得到'numStrBytes'值是正确的值? –

+0

呃。傻我。不是,报告的长度是892942715 ..我必须找出原因。稍后会报告回来! – Sam

+1

@HuRRaCaNe:这是“599 {”,位于ascii/utf8。可能是一个前缀为字符串而不是二进制的长度。 –

回答

2

感谢Lasse和Stephen(对问题的评论),因为他们是对的。数据长度的确是以数据为前缀,然后作为字节复制,而不是先将文本作为字节获取,然后将长度作为字节前缀。

所以我做的是创建一个新的总长度(有效载荷)的字节数组,然后获取数据的字节,然后用数据的长度填充前4个字节。像这样:

转让之前:

// Add the length of the data at the start, so we know how much characters to read when receiving this 
Int32 dataLength = data.Length; 
// Add the data to be sent into the buffer 
byte[] payload = new byte[sizeof(Int32) + (dataLength * sizeof(char))]; 
byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(data); 
System.Buffer.BlockCopy(dataBytes, 0, payload, 4, dataBytes.Length); 

payload[0] = (byte)(dataLength >> 24); 
payload[1] = (byte)(dataLength >> 16); 
payload[2] = (byte)(dataLength >> 8); 
payload[3] = (byte)dataLength; 

当接收:

var stringHeader = await reader.LoadAsync(4); 
Int32 strLength = reader.ReadInt32(); 
uint numStrBytes = await reader.LoadAsync((uint)strLength); 
string data = reader.ReadString(numStrBytes); 
+0

您应该查看[BinaryWriter](http://msdn.microsoft.com/en-us/library/system.io.binarywriter.aspx)和[BinaryReader](http://msdn.microsoft.com/zh-cn/我们/库/ system.io.binaryreader(v = vs.110)的.aspx)。 –

+2

我猜你的意思是“感谢Lasse和Stephen”:)我可能有点奇怪,但我肯定不是精神分裂症。我也不是! –

相关问题