【问题标题】:NetworkStream.Read throws no exceptionNetworkStream.Read 不抛出异常
【发布时间】:2016-04-08 12:49:41
【问题描述】:

我无法运行此示例: https://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient%28v=vs.110%29.aspx

我对他们的代码所做的唯一更改是将所有内容都放在 main 方法中,当然还有我的端口名称。我可以连接到我的服务器,甚至可以发送数据。但是就行了

Int32 bytes = networkStream.Read(data, 0, data.Length); 

程序无异常停止运行。微软自己的代码怎么不能工作?我的服务器还没有发送任何东西,但我认为这不重要吗? (虽然它接收得很好。)我读过一些你不能在其他线程中看到异常的东西,但我没有。 我也试过这个线程: C# tcp socket (networkstream.read won't work with 8.1)

它不起作用。我跑赢 7 thoguh。但我希望这适用于全新的窗口。

【问题讨论】:

  • 读取是同步调用。你从服务器发送什么?
  • Read() 将阻塞/停止,直到收到一些数据。作为此阻塞的解决方法,您可以在阅读之前添加if(networkStream.IsDataAvailable)。这样,它应该永远不会阻塞。
  • @ThariqNugrohotomo 如果它返回 false 怎么办?这并不意味着没有数据! IsDataAvailable 不适用于此。
  • @usr 根据我过去的经验,它可以工作。如果仍然返回 false,可能是你忘记刷新数据,可能接收到的数据仍然太小,或者底层 Stream 实现有问题。
  • 或者,数据还在网络中,很快就会到。它不能工作。

标签: c# tcp networkstream


【解决方案1】:

NetworkStream.Read 阻塞直到数据可用、连接关闭(在这种情况下它将返回0)或发生异常。就是这样设计的。

如果您的服务器将发送数据,您的客户端程序将继续并能够处理响应。

【讨论】:

  • 看来是这样。我必须说非常奇怪的行为。该命令的执行似乎也发生了变化,因为在线的旧示例都在其 while 循环中使用了类似 read 的东西。我现在必须使用类似 while(stream.dataavailble) 的东西,然后在 while 循环中读取。
  • @StaffanMattsson :执行没有变化。这些示例在循环中有Read(),因为它们可能负担得起该块(即它在另一个线程中)。如果我没记错的话,它一直在阻塞。
  • @StaffanMattsson :早在 .NET Framework 1.1 的 NetworkStream.Read() 文档中甚至已经指出 “如果没有数据可供读取,NetworkStream.Read 方法将阻塞,直到数据可用。”。链接:msdn.microsoft.com/en-us/library/…
  • 这种阻塞行为允许将NetworkStream 传递给任何期望Stream 的对象,例如XmlSerializer
  • @StaffanMattsson 恕我直言,这种设计是大多数开发人员实际需要的。我们不希望它立即返回零数据,说什么都没有收到,如果把它放在循环中可能会有效地变成一个占用大量 cpu 时间的繁忙循环。阻塞行为是在没有接收到数据时节省 cpu 时间。
【解决方案2】:

NetworkStream.Read() 是一个同步调用,它会一直等到收到响应。要读取不同长度的数据,您可以执行以下操作。

注意:我假设服务器只发送一个请求响应。

private string GetResponse(string command)
{
    //Send request
    TcpClient client = new TcpClient(HOST, PORT);
    Byte[] data = Encoding.ASCII.GetBytes(command);
    NetworkStream stream = client.GetStream();
    stream.Write(data, 0, data.Length);

    //Read response
    data = new Byte[BUFFER_SIZE];
    String response = String.Empty;
    stream.ReadTimeout = READ_TIMEOUT;
    while (!response.EndsWith(RESPONSE_END))
    {
        int bytes = stream.Read(data, 0, data.Length);
        response += Encoding.ASCII.GetString(data, 0, bytes);
    }
    response = response.Remove(response.Length - RESPONSE_END.Length);
    stream.Close();
    client.Close();

    //Return
    return response;
}

【讨论】:

  • 这有一个错误,因为它可以一次读取多条消息,或者一条消息加上部分消息。
  • @usr True,如果服务器发送了多个响应。在这个例子中,我假设服务器只发送一个请求响应。
  • 对,我没有想到这种可能性。
  • @usr 感谢您更详细地查看代码。
猜你喜欢
  • 2017-04-02
  • 1970-01-01
  • 2012-01-24
  • 2013-05-24
  • 2010-12-09
  • 2016-02-27
  • 2015-12-13
  • 2021-11-21
  • 1970-01-01
相关资源
最近更新 更多