2008-10-03 187 views
4

對於我當前的項目,我需要通過tcp/ip套接字連接請求XML數據。爲此,我正在使用TcpClient類:.NET中的TCP/IP套接字連接

Dim client As New TcpClient() 
client.Connect(server, port) 

Dim stream As NetworkStream = client.GetStream() 
stream.Write(request) 
stream.Read(buffer, 0, buffer.length) 

// Output buffer and return results... 

現在,這可以正常工作,對於小反應很好。但是,當我開始接收更大的數據塊時,看起來數據會以突發形式推送到套接字連接上。當發生這種情況時,stream.Read調用只會讀取第一個突發,因此我錯過了其他響應。

解決此問題的最佳方法是什麼?最初我試圖循環,直到我有一個有效的XML文檔,但我發現在stream.Read調用之間,底層流有時會關閉,我會錯過最後一部分數據。

回答

3

您創建一個閱讀循環。

Stream.Read返回int,表示到目前爲止讀取的字節數,如果到達流結尾,則返回0。

所以,它像:

int bytes_read = 0; 
while (bytes_read < buffer.Length) 
    bytes_read += stream.Read(buffer, bytes_read, buffer.length - bytes_read); 

編輯:現在的問題是,你如何確定緩衝區的大小。如果你的服務器第一次發送大小,沒關係,你可以使用上面的代碼片段。但是如果你必須閱讀直到服務器關閉連接,那麼你必須使用try/catch(即使你知道這個大小也是個好主意),並且使用bytes_read來確定你收到的東西。

int bytes_read = 0; 
try 
{ 
    int i = 0; 
    while (0 < (i = stream.Read(buffer, bytes_read, buffer.Length - bytes_read)) 
     bytes_read += i; 
} 
catch (Exception e) 
{ 
//recover 
} 
finally 
{ 
if (stream != null) 
    stream.Close(); 
} 
+0

這就是我所做的,但底層流在閱讀之間關閉。人們如何解釋這一點? – 2008-10-03 19:14:22

2

閱讀不能保證完全讀取流。它返回讀取的實際字節數,如果沒有更多字節要讀取,則返回0。您應該循環讀取流中的所有數據。

0

這是一種可行的方法,並獲得響應字符串的「響應」。如果你需要字節數組,只需保存ms.ToArray()即可。

string response; 

TcpClient client = new TcpClient(); 
client.Connect(server, port); 
using (NetworkStream ns = c.GetStream()) 
using (MemoryStream ms = new MemoryStream()) 
{ 
    ns.Write(request); 

    byte[] buffer = new byte[512]; 
    int bytes = 0; 

    while(ns.DataAvailable) 
    { 
     bytes = ns.Read(buffer,0, buffer.Length); 
     ms.Write(buffer, 0, bytes); 
    } 

    response = Encoding.ASCII.GetString(ms.ToArray()); 
} 
0

我強烈建議您嘗試WCF這樣的任務。它在不太陡峭的學習曲線之後爲您提供了比原始套接字通信更多的好處。 對於手頭的任務,我同意前面的答案,您應該使用循環並根據需要動態分配內存。