2016-08-24 2 views
0

В настоящее время я пишу клиентское/серверное приложение и должен отправлять файлы (музыку, видео, текст и любой другой вид) с сервера на клиент. В настоящее время я написал две следующие функции:Отправка файла через TCP с помощью двоичной сериализации/десериализации

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: конец потока, встречающийся до разбора, был завершен.

Если я обхожу копирование FileStream к MemoryStream и вызовите formatter.Deserialize fStream вместо этого, я получаю следующее исключение в том же месте:

System.Runtime.Serialization.SerializationException: входной поток не действительный двоичный формат. Исходное содержание (в байтах), является: байт

Почему мой BinaryFormatter не в состоянии десериализации моего содержимого файла?

EDIT:

Чтобы убедиться, что мой поток содержит байты, я также попытался следующие, но я получаю тот же 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 
+0

Вы звоните в 'formatter.Deserialize mStream' происходит после области' use', поэтому в это время 'mStream' будет удален. Интересно, почему вы не получаете «ObjectDisposedException» ... –

+0

Возможно, это было так, как я написал это, что немного неясно, но на самом деле это фильтр, который становится доступным и используется только между круглыми скобками. – Choub890

ответ

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.

Смежные вопросы