Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET TCP客户端为空&;非空返回流_C#_.net_Tcpclient - Fatal编程技术网

C# .NET TCP客户端为空&;非空返回流

C# .NET TCP客户端为空&;非空返回流,c#,.net,tcpclient,C#,.net,Tcpclient,当有数据返回时,下面的操作正常。但是,对于返回的空流来说,下面的代码挂起在stream.read()上是有效的。如何重构它以满足这两种情况 using(TcpClient client = new TcpClient(_server, _port)) using(NetworkStream stream = client.GetStream()) { stream.Write(data, 0, data.Length);

当有数据返回时,下面的操作正常。但是,对于返回的空流来说,下面的代码挂起在stream.read()上是有效的。如何重构它以满足这两种情况

        using(TcpClient client = new TcpClient(_server, _port))
        using(NetworkStream stream = client.GetStream())
        {
            stream.Write(data, 0, data.Length);

            byte[] myReadBuffer = new byte[1024];

            int numberOfBytesRead = 0;

            var message = new List<Byte> ();

            do{
                numberOfBytesRead = stream.Read(myReadBuffer, numberOfBytesRead, myReadBuffer.Length);

                message.AddRange(myReadBuffer.Take(numberOfBytesRead));

            }
            while(stream.DataAvailable);         

            return message.ToArray();
        }
使用(TcpClient客户端=新的TcpClient(\u服务器,\u端口))
使用(NetworkStream=client.GetStream())
{
stream.Write(数据,0,数据长度);
字节[]myReadBuffer=新字节[1024];
int numberOfBytesRead=0;
var message=newlist();
做{
numberOfBytesRead=stream.Read(myReadBuffer,numberOfBytesRead,myReadBuffer.Length);
message.AddRange(myReadBuffer.Take(numberOfBytesRead));
}
while(stream.DataAvailable);
返回消息。ToArray();
}

如果我正确理解了代码示例,您真正想做的就是从套接字(即TCP连接)读取所有字节,然后将它们作为
字节[]
返回。如果是这样的话,那么这会更好:

    using(TcpClient client = new TcpClient(_server, _port))
    using(NetworkStream stream = client.GetStream())
    using(MemoryStream output = new MemoryStream())
    {
        stream.CopyTo(output);
        return output.ToArray();
    }
一般来说,我强烈建议不要使用
DataAvailable
属性。在这种情况下,它尤其不合适,因为它所做的只是检查可以从流中读取多少字节,如果它不是零,则返回
true
。空流永远不会有可用的字节,因此,即使流不是空的,您也永远不会检测到流的结尾(即,无法判断另一端何时向您发送数据)


如果我误解了,而您真的只想返回立即可用的字节,那么如果没有更多的上下文,我无法提供答案。实现这一点的正确方法是使用异步I/O,该层理解流的整体结构(即数据边界所在的位置),但实现所需的细节在您的问题中没有给出,因此,不可能按照这些思路提供具体的建议。

您永远无法判断是否会有更多的数据到来,或者数据流是否耗尽。远端必须向您发出流结束的信号

通过关闭或关闭套接字,您将读取
0
字节,这是您停止读取的信号

或者,让远程端发送数据信号,表示流的结束

您对
DataAvailable
的使用是一个bug(99%的使用是bug)<代码>数据可用有毒。它告诉您现在有多少数据可以以非阻塞方式读取。1我们以后的答案可能会有所不同


你需要把它扔掉。

你的理解是正确的。不幸的是,对于这两种情况,代码现在都在.CopyTo处阻塞。我想这可能是NetworkStream特有的功能。@mylescdonnell:如果
CopyTo()
阻塞,则远程终结点的行为不正常。也就是说,当完成发送时,它应该对连接进行优雅的关闭。注意,假设流是“连接,发送所有数据,关闭连接”。如果您希望保持连接打开,以便以后可以发送更多数据,则需要更改协议,以便有一种机制来分隔同一连接上的各个传输(例如,在传输之前使用字节长度)异步IO的有趣之处;响应流只是一个任意长度的字节[],它不需要以任何方式进行解释/解析。@MyleSCdonnell:在我看来,最直接的问题是,您是否希望服务器在发送响应后关闭连接?如果是这样,那么如果
CopyTo()
阻塞,服务器似乎没有关闭连接。如果您不希望连接关闭,那么您需要解释如何确定该连接上任何给定响应的长度。是否可以改用
HttpClient
类?您在这里处理的是什么类型的服务器?它是我用Erlang编写的TCP服务器,所以我怀疑您是正确的;服务器实现错误。是的,我已经完成了,谢谢。这是我第一次涉足网络编程这个层次,所以我犯了书中的每一个错误。