4

对于我当前的项目,我需要通过 tcp/ip 套接字连接请求 XML 数据。为此,我正在使用 TcpClient 类:

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 调用之间,底层流有时会被关闭,我会错过数据的最后一部分。

4

4 回答 4

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();
}
于 2008-10-03T19:12:00.077 回答
2

不保证读取完全读取流。它返回实际读取的字节数,如果没有更多字节要读取,则返回 0。您应该继续循环以从流中读取所有数据。

于 2008-10-03T19:17:05.700 回答
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());
}
于 2009-02-11T22:05:38.443 回答
0

我强烈建议您尝试使用 WCF 来完成此类任务。经过不那么陡峭的学习曲线后,它为您提供了比原始套接字通信更多的好处。对于手头的任务,我同意前面的答案,您应该使用循环并根据需要动态分配内存。

于 2009-05-04T10:33:17.413 回答