2012-11-07 97 views
2

我正在處理一個C#應用程序,它在網絡實例之間傳遞字符串。從套接字緩衝字符串流

該代碼當前正在使用異步套接字,並且到目前爲止一切正常(localhost)。

但是,我期待緩衝問題,當數據包將被拆分和合並時,我會經歷真正的接口。

客戶:

Socket sock; 
// Snip init and connect 

string msg1 = "Hello\nWorld"; 
byte[] data1 = System.Text.Encoding.UTF8.GetBytes(msg1); 
sock.Send(data1); 

string msg2 = "Foo\nBar\nBaz"; 
byte[] data2 = System.Text.Encoding.UTF8.GetBytes(msg2); 
sock.Send(data2); 

我會去像這樣的東西,但我不能想出一個優雅的解決缺少位:

服務器:

Socket sock; 
MemoryStream ms = new MemoryStream(); 
Queue<string> strings = new Queue<string>(); 
// Snip init and receive connection 
sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null); 

void OnReceived(IAsyncResult result) { 
    // Snip sanity stuff 
    int bytesReceived = sock.EndReceive(result); 

    // Here is where I'd need some help... 
    ms.Write(buffer, 0, bytesReceived); 
    ms.Flush(); 
    for (;;) { 
    StreamReader sr = new StreamReader(ms); 
    if (sr.HasAStringTerminationCharacter) { // <-- How? 
     string currentString = sr.ReadUntilTermination(); // <-- How? 
     strings.Enqueue(currentString); 
    } 
    else 
     break; 
    } 
    sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null); 
} 
+0

位於此處的msdn示例(http://msdn.microsoft.com/en-us/library/fx6588te%28v=vs.90%29.aspx)看起來好像可能有所幫助 - 檢查ReadCallbackMethod – Johnv2020

+0

@ Johnv2020這讓我意識到Encoding.GetBytes不會附加或預先加載字符串終止數據,所以沒有辦法通過該協議來完成。 –

回答

0

由於Encoding.GetBytes()不會預先添加或附加字符串終止數據,所以我使用了BinaryReader/BinaryWriter,它在內容之前編碼字符串長度。

下面是修改後的客戶端:

Socket sock; 
// Snip init and connect 
sock.Send(ToBinary("Hello\nWorld")); 
sock.Send(ToBinary("Foo\nBar\nBaz")); 

byte[] ToBinary(string s) { 
    var ms = new MemoryStream(); 
    var bw = new BinaryWriter(ms); 
    bw.Write(s); 
    bw.Flush(); 
    ms.Flush(); 
    return ms.ToArray(); 
} 

服務器:

Socket sock; 
MemoryStream ms = new MemoryStream(); 
Queue<string> strings = new Queue<string>(); 
// Snip init and receive connection 
sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null); 

void OnReceived(IAsyncResult result) { 
    // Snip sanity stuff 
    int bytesReceived = sock.EndReceive(result); 

    ms.Write(buffer, 0, bytesReceived); 
    ms.Flush(); 
    long endPos = ms.Position; 

    ms.Seek(0, SeekOrigin.Begin); 
    long readPos = ms.Position; 
    var bw = new BinaryReader(ms); 

    for (;;) { 
    try { 
     string currentString = bw.ReadString(); 
     strings.Enqueue(currentString); 
     readPos = stream.Position; 
    } 
    catch (EndOfStreamException) { 
     long unusedBytes = endPos - readPos; 
     var remaining = new MemoryStream(); 
     remaining.Write(stream.GetBuffer(), (int) readPos, (int) unusedBytes); 
     ms = remaining; 
     break; 
    } 
    } 
    sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null); 
} 

我相信它會正確處理拆分和合並數據。