2014-05-09 59 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」:)我可能有點奇怪,但我肯定不是精神分裂症。我也不是! –

相關問題