【问题标题】:Tcp/Ip Socket connections in .NET.NET 中的 Tcp/Ip 套接字连接
【发布时间】:2010-09-15 04:02:04
【问题描述】:

对于我当前的项目,我需要通过 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 调用之间,底层流有时会被关闭,我会错过数据的最后一部分。

【问题讨论】:

    标签: asp.net sockets tcp


    【解决方案1】:

    这是一种可能的方法来“响应”响应字符串。如果您需要字节数组,只需保存 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());
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案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);
        

        编辑:现在,问题是如何确定缓冲区的大小。如果你的服务器先发送大小,那没关系,你可以使用上面的sn -p。但是,如果您必须在服务器关闭连接之前读取,那么您必须使用 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();
        }
        

        【讨论】:

        • 这就是我所做的,但底层流在读取之间变得关闭。如何解释这一点?
        • 把它放在 try/catch 块中。如果流关闭,很可能您的服务器无法正常运行。
        • 另外,我不知道每个响应应该接收多少字节。
        • 服务器没问题。我使用程序跟踪了响应,它确实发送了完整的响应。问题是连接只支持每次传输一定数量的字节。完成传输后,它会关闭底层流。
        • Read 可以在 EOF 上返回 0 - 我认为最好在循环中检查它,因为它会继续返回 0 或抛出。
        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-02
          • 2014-04-08
          • 2013-06-29
          • 2011-09-20
          • 2015-05-15
          • 2014-12-10
          • 2011-08-31
          相关资源
          最近更新 更多