通过TCP使用二进制序列化/反序列化发送文件

时间:2016-08-24 21:24:20

标签: .net serialization tcp f# deserialization

我目前正在编写客户端/服务器应用程序,需要将文件(音乐,视频,文本和任何其他类型)从服务器发送到客户端。目前,我写了以下两个函数:

let sendFile (client:TcpClient) (srcFilePath:string) = 
    let formatter = new BinaryFormatter()

    // Deserialize message content to obj
    use mStream = new MemoryStream()
    (   
        use fStream = File.OpenRead srcFilePath
        fStream.CopyTo mStream 
    )
    let deserializedContent = formatter.Deserialize mStream

    // Create and serialize message into network stream
    let message = { Type = FileSync; Content = Some deserializedContent }
    formatter.Serialize (client.GetStream (), message)

将文件发送到客户端,并在客户端将其接收:

let readStreamToFile (client:TcpClient) outputPath =
    let formatter = new BinaryFormatter()

    try
        let message = (formatter.Deserialize (client.GetStream ())) :?> Message
        match message.Type with
        | FileSync ->
            use fileStream = File.Open(outputPath, FileMode.Create)
            match message.Content with
            | Some content ->
                formatter.Serialize (fileStream, message.Content)
            | None ->
                failwith "There was no content in the FileSync message!!!"
        | _ ->
            ()
    with
    | :? InvalidCastException as ex ->
        failwith "Message format unknown!!!"

调用formatter.Deserialize mStream时,我收到以下异常:

  

System.Runtime.Serialization.SerializationException:解析完成之前遇到的Stream of End。

如果我绕过将FileStream复制到MemoryStream,然后拨打formatter.Deserialize fStream,我会在同一位置收到以下异常:

  

System.Runtime.Serialization.SerializationException:输入流不是有效的二进制格式。起始内容(以字节为单位)为: bytes

为什么我的BinaryFormatter无法反序列化我的文件内容?

编辑:

为了确保我的流包含字节,我也尝试了以下内容,但是我得到了相同的The input stream is not a valid binary format异常:

// Deserialize message content to obj
let fileBytes = File.ReadAllBytes srcFilePath
use mStream = new MemoryStream()
mStream.Write (fileBytes, 0, fileBytes.Length)
mStream.Position <- (int64)0
let deserializedContent = formatter.Deserialize mStream

1 个答案:

答案 0 :(得分:1)

如果您的源文件是音乐,视频等,则其内容不会被.NET序列化。因此,反序列化它们将不起作用,这就是抛出异常的原因。您应该按原样阅读文件,而不进行反序列化:

let sendFile (client:TcpClient) (srcFilePath:string) = 
    let formatter = new BinaryFormatter()

    let fileContent = File.ReadAllBytes srcFilePath

    // Create and serialize message into network stream
    let message = { Type = FileSync; Content = Some fileContent }
    formatter.Serialize (client.GetStream (), message)

与此一致,您不应该在客户端序列化文件内容:

let readStreamToFile (client:TcpClient) outputPath =
    let formatter = new BinaryFormatter()

    try
        let message = (formatter.Deserialize (client.GetStream ())) :?> Message
        match message.Type with
        | FileSync ->
            match message.Content with
            | Some content ->
                File.WriteAllBytes(outputPath, content)
            | None ->
                failwith "There was no content in the FileSync message!!!"
        | _ ->
            ()
    with
    | :? InvalidCastException as ex ->
        failwith "Message format unknown!!!"

请注意,我已将内容类型从obj option更改为byte[] option