对于我当前的项目,我需要通过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调用之间,底层流有时会被关闭,我会错过最后一部分数据。
答案 0 :(得分: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();
}
答案 1 :(得分:2)
不保证读取完全读取流。它返回读取的实际字节数,如果没有更多字节要读,则返回0。你应该继续循环来读取流中的所有数据。
答案 2 :(得分: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());
}
答案 3 :(得分:0)
我强烈建议您尝试WCF执行此类任务。在不那么陡峭的学习曲线之后,它为您提供了比原始套接字通信更多的好处。 对于手头的任务,我同意前面的答案,你应该使用循环并根据需要动态分配内存。