在.NET中的Tcp/Ip Socket连接

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个回答

3

您需要创建一个循环来进行读取。

Stream.Read返回已经读取的字节数,如果到达流的末尾则返回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();
}

这就是我所做的,但在读取过程中底层流被关闭了。如何解决这个问题? - Kevin Pang
将其放在try/catch块中。如果流已关闭,则很可能是您的服务器未正常运行。 - Sunny Milenov
另外,我不知道每个响应应该接收多少字节。 - Kevin Pang
服务器没问题。我用程序跟踪了响应,它确实发送了完整的响应。问题在于连接每次传输只支持一定数量的字节。传输完成后,它会关闭底层流。 - Kevin Pang
读取函数在遇到文件结束符时会返回0 -- 我认为最好在循环中检查这个,因为它要么一直返回0,要么抛出异常。 - Lou Franco

2

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


0

我强烈建议您尝试使用WCF来完成这样的任务。在经过一定的学习曲线后,它可以为您提供许多优于原始套接字通信的好处。 对于手头的任务,我同意之前的答案,您应该使用循环并根据需要动态分配内存。


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());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接