【发布时间】:2014-06-21 03:22:24
【问题描述】:
我遇到了两个问题,在尝试了一些我在 stackoverflow 上阅读过的技术后,问题仍然存在。我正在尝试使用下面的代码将文件从服务器发送到客户端,但问题是文件总是几个字节短,导致文件损坏。第二个问题是尽管实现了流并没有关闭最后一个零长度的数据包,表示传输完成而没有关闭连接。
服务器代码sn-p:
/*
* Received request from client for file, sending file to client.
*/
//open file to send to client
FileStream fs = new FileStream(fileLocation, FileMode.Open, FileAccess.Read);
byte[] data = new byte[1024];
long fileSize = fs.Length;
long sent = 0;
int count = 0;
while (sent < fileSize)
{
count = fs.Read(data, 0, data.Length);
netStream.Write(data, 0, count);
sent += count;
}
netStream.Write(new byte[1024], 0, 0); //send zero length byte stream to indicate end of file.
fs.Flush();
netStream.Flush();
客户端代码sn-p:
TcpClient client;
NetworkStream serverStream;
/*
* [...] client connect
*/
//send request to server for file
byte[] dataToSend = SerializeObject(obj);
serverStream.Write(dataToSend, 0, dataToSend.Length);
//create filestream to save file
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
//handle response from server
byte[] response = new byte[client.ReceiveBufferSize];
byte[] bufferSize = new byte[1024];
int bytesRead;
while ((bytesRead = serverStream.Read(bufferSize, 0, bufferSize.Length)) > 0 && client.ReceiveBufferSize > 0)
{
Debug.WriteLine("Bytes read: " + bytesRead);
fs.Write(response, 0, bytesRead);
}
fs.Close();
【问题讨论】:
-
你从哪里得到发送零字节应该神奇地关闭流?
-
我不认为它会“神奇地关闭流”,但我不完全确定之后如何检查零长度流。我想也许是 client.ReceivedBufferSize 但这显然是错误的。这个答案在这里提到了stackoverflow.com/a/13524750/1364673我对文件传输真的很陌生,我花了过去 8 个小时来尝试构建一个基本的客户端/服务器应用程序来传输大小文件。
-
请记住,使用 TCP,仅仅因为您调用
netStream.Write()并不意味着您提交的内容要么 (a) 立即发送,要么 (b) 将发送作为一个单独的数据包。底层套接字提供程序决定如何将所有内容分成数据包以及何时/如何发送它们。具体来说,它可以将多个写入捆绑到一个数据包中,以减少“喋喋不休”。我不确定 TCP 应该如何处理 0 字节写入,但一个非常合理的选择是完全忽略它。 -
我认为 Jon Skeet 指的是在块之前写出块的大小和最后的大小为零。
-
不管整个发送一个零长度字节数组来表示传输结束,为什么这个流在字节大小的最后会变短?我的意思是它会传输 99% 的文件,但它总是只是缺少完全传输的文件,这会阻止它在另一端打开。例如,我从服务器向客户端发送了一个 MP3,但文件不完整且无法播放。
标签: c# filestream tcpclient file-transfer networkstream