2008-10-03 155 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这样的任务。它在不太陡峭的学习曲线之后为您提供了比原始套接字通信更多的好处。 对于手头的任务,我同意前面的答案,您应该使用循环并根据需要动态分配内存。