簡體   English   中英

服務器在發送后立即關閉時從NetworkStream讀取數據

[英]Reading data from NetworkStream when server closes immediately after sending

我正在使用BinaryReaderStream序列化對象:

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();
    }
}

應該不是問題。 如果服務器確實只發送了所有數據,然后以有序的方式關閉流,那么您應該能夠獲取它發送的所有數據。 如果連接以一種不那么有序的方式終止,或者在其他地方丟棄,你可能會看到一個問題,並且可能在你已經返回它已經關閉的事實繼續嘗試從中讀取。

如果您不使用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 ...它應該只是退出循環。 如果這樣做但你現有的代碼拋出,你需要檢查你在閱讀代碼中做出的假設(你還沒有發布)。

這會導致IOException(“Connection closed ...”)

這更可能是因為你的一方關閉連接然后試圖從中讀取。 遠程關閉應該只是導致EOS條件在API中表現出來的各種方式之一。

如果傳入的TCP FIN意味着連接已關閉,那將是一個重大的錯誤:它可能是一個關閉,另一個方向仍然可以運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM