服务器在发送后立即关闭时从NetworkStream读取数据

时间:2012-03-19 14:19:19

标签: c# .net serialization io

我正在使用Stream来序列化BinaryReader中的对象:

class MyClass
{
    public void Read(Stream stream)
    {
        BinaryReader reader = new Reader(stream);

        this.someField = reader.ReadSomething(); // IOException
    }
}

在一种情况下的问题是,如果我从NetworkStream读取,服务器在发送数据后立即关闭连接。这导致IOException (“无法从传输连接读取数据:远程主机强行关闭现有连接。”) 甚至在我之前阅读我身边的所有内容。我该如何阅读这些数据?它不是在某处缓冲的吗?

我正在阅读的协议是 TLS ,如果服务器发送致命警报,我想要读取该警报,之后连接应立即关闭侧上。

异常消息:

System.IO.IOException
  Message=Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
  Source=System
  StackTrace:
       at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
       at System.IO.Stream.ReadByte()
       at System.IO.BinaryReader.ReadByte()
       at MyClass.Read(Stream stream)
    [...]
  InnerException: System.Net.Sockets.SocketException
       Message=An existing connection was forcibly closed by the remote host
       Source=System
       ErrorCode=10054
       NativeErrorCode=10054
       StackTrace:
            at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

class Record
{
    public void Read(Stream stream)
    {
        BinaryReader reader = new BinaryReader(stream);

        byte contentType = reader.ReadByte();
        byte majorVer = reader.ReadByte();
        byte minorVer = reader.ReadByte();
        ushort payloadSize = reader.ReadUInt16();

        if(contentType == 21) // Alert
        {
            Alert alert = new Alert();
            alert.Read(stream);
        }
    }
}

class Alert
{
    public void Read(Stream stream)
    {
        BinaryReader reader = new BinaryReader(stream);

        byte level = reader.ReadByte(); // IOException
        byte desc = reader.ReadByte();
    }
}

2 个答案:

答案 0 :(得分:2)

不应该成为问题。如果服务器确实只发送了所有数据,然后以有序的方式关闭了流,那么应该能够获取它发送的所有数据。如果连接以不那么有序的方式终止,或者在其他地方丢弃,你会看到一个问题,并且可能如果你继续尝试从中读取,它已经返回它已经关闭的事实。

如果您不使用BinaryReader会发生什么,但只需使用该流并执行以下操作:

// Just log how much data there is...
byte[] buffer = new byte[8 * 1024];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
    Console.WriteLine(bytesRead);
}

由于套接字正常关闭,不应抛出IOException ...它应该只是退出循环。如果这样做但你现有的代码抛出,你需要检查你在阅读代码中做出的假设(你还没有发布)。

答案 1 :(得分:0)

  

导致IOException(“Connection closed ...”)

这可能是由你的身边关闭连接然后尝试从中读取而引起的。远程关闭应该只是导致EOS条件在API中出现的各种方式之一。

API假设传入的TCP FIN意味着连接已关闭是一个重大错误:它可能是关闭,另一个方向仍然可以运行。