C#TcpClient和NetworkStream通过TCP发送/接收数据。为什么不使用“使用”块,我可以在将数据写入流后立即读取数据吗?

问题描述 投票:0回答:1

我正在阅读有关使用TcpClient和NetworkStream来编写和读取Tcp连接流的文档。但我注意到,即使TcpClient和NetworkStream都实现了IDisposable,所有Microsoft的文档都没有使用“using”块。

所以,我想知道为什么会这样。

我还注意到在一些例子中他们写入流然后立即从流中读取。这感觉不对,但我是网络新手,但我写了类似下面的代码来做到这一点。

虽然代码有效,但我不确定它有多好和可靠。具体来说,如果无法读取数据,一旦我检查它,执行将继续。那时,数据可能可供阅读,但是到时候为止,我已经通过了这一点。

我的问题大写为下面的代码注释

using (TcpClient client = new TcpClient())  // WHY NOT USING?
{
    client.Connect(ip, port);

    using (NetworkStream stream = client.GetStream())  // WHY NOT USING?
    {
        byte[] messageBytes = ...;
        if (stream.CanWrite)
        {
            await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
            stream.Flush();
        }

        // IS THIS DATA GOING TO BE AVAILABLE AT THIS POINT?  
        // IF NOT, THEN YOU WILL HAVE NO OPPORTUNITY TO READ DATA 
        // SINCE NOTHING IS GOING TO TELL YOU WHEN IT IS GOING TO BE AVAILABLE.  
        // BY THE TIME IT IS AVAILABLE, THE EXECUTION MAY PASS THIS POINT, WHAT THEN???
        if (stream.CanRead)  
        {
            byte[] buffer = newe byte[1024];
            int readSoFar = 0;
            StringBuilder builder = new StringBuilder();

            while(stream.DataAwailable)
            {
                readSoFar = await stream.ReadAsync(buffer, 0, buffer.Length);
                builder.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, readSoFar));
            }

            string msg = builder.ToString();
        }
    }
}
c# xamarin.forms tcpclient networkstream using-statement
1个回答
2
投票

TcpClient / NetworkStream / Socket只有一个非管理资源。这是套接字本身。你的代码只能有1个使用块,你就可以了。在您的示例中,当代码离开using (NetworkStream)块时,它会关闭底层套接字,而TcpClient.Dispose实际上什么都不做。

关于Read / ReadAsync。数据无法立即获得。但是这些方法等待2个事件之一:数据出现在套接字上,或者其他方关闭tcp套接字。一旦插槽上出现1个字节,这些函数会立即返回结果。如果另一方关闭连接,这些函数将返回0,它实际上表示流的结束。

通常你不应该使用DataAvailable属性。在您的示例中,它可能会导致意外行为。您可以使用Read / ReadAsync直到它们返回零。

© www.soinside.com 2019 - 2024. All rights reserved.