通过 TCP 发送/接收文件 [重复]
Posted
技术标签:
【中文标题】通过 TCP 发送/接收文件 [重复]【英文标题】:Send / receive file over TCP [duplicate] 【发布时间】:2012-11-11 13:24:36 【问题描述】:可能重复:TcpClient send data and receive data over networkLoop until TcpClient response fully read
我正在尝试通过 TCP 将文件从服务器发送到客户端。
服务器端代码,发送文件:
NetworkStream netStream = client.GetStream();
FileStream fs = new FileStream("usb.exe",FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data,0, data.Length);
fs.Flush();
fs.Close();
netStream.Write(data, 0, data.Length);
netStream.Flush();
客户端代码,接收文件:
FileStream str = new FileStream("usb.exe", FileMode.Create, FileAccess.Write);
byte[] data = new byte[1024];
while ((dataCitit = netStream.Read(data,0, data.Length)) > 0)
Thread.Sleep(25);
Application.DoEvents();
str.Write(data, 0, dataCitit);
totalbytes += dataCitit;
str.Close();
有人能指出我哪里弄错了吗?
该文件有 1036 kb,它只发送 1032 kb,然后卡住它不会退出客户端的 while 循环。
此外,如果我关闭服务器并快速打开它,它会发送最后一个字节并且文件会完全发送。 (此文件完美打开)
我认为这是服务器端的问题,没有发送所有字节,但是为什么以及在哪里......
【问题讨论】:
这个答案似乎对你有帮助:***.com/a/8028242/1108263 【参考方案1】:这是您的服务器端代码中的一个问题:
fs.Read(data,0, data.Length);
您忽略了Read
返回的值。 永远不要那样做。使用FileStream
,您可能没问题,但我个人无论如何都不会相信它。如果您使用的是 .NET 4,则无论如何都不需要这样做 - 只需使用 Stream.CopyTo
。
在客户端代码上,您最初的最大问题是您在 UI 线程上执行所有这些操作。这是一个糟糕的想法 - 如果出现网络故障,UI 将冻结,因为 Read
调用被阻塞。
同样,只需使用Stream.CopyTo
,但在后台线程中执行。
此外,在所有这些情况下,对流使用using
语句,这样无论发生什么都可以干净地关闭它们。
这只是一般卫生。现在,至于你为什么挂...
...您没有关闭服务器端的网络流。因此,您永远不会到达客户端流的 end。如果只需要对单个文件使用连接,那么答案很简单:关闭服务器端的连接即可。
但是,如果您需要对多个文件使用相同的连接,那么您需要更多的协议 - 您需要某种方式来指示数据的结束。有三种常见的方法:
在数据本身之前写入数据的长度,然后在读取端,首先读取长度,然后读取那么多字节,如果流在您完成之前完成则失败。这要求您在开始写入之前知道要写入多少数据。 使用可以在读取端检测到的“数据结束”标记;一般来说,这很痛苦,因为如果它出现在文本本身中,它需要转义标记。 第一种方法的变体,您一次写入一个以长度为前缀的块,然后写入一个零长度块以指示“数据结束”。这非常灵活,但如果第一种方法确实适合您,那么显然比第一种方法要多一些工作。【讨论】:
谢谢你的回答,我只是来编辑我的问题。就像你说的,这是因为我没有关闭服务器端的 NetworkStream。我将放弃您的建议并使用上述方法,因为我不想关闭流。再次感谢您。 另外,如果您可以向我展示第一种写入数据长度的方法的示例,如果将非常有用。 @Spreadzz:不,您应该自己尝试一下,然后在遇到问题时提出具体问题。您可能需要考虑使用BinaryWriter
和BinaryReader
,这会使事情变得更简单。
如果我错了,请纠正我 BinaryReader 和 BinaryWriter 用于写入和读取以及数据标记结束?
还有一个问题,在客户端我的 int dataCitit = netStream.Read(data,0, data.Length) 如果我不关闭服务器端的流,是否会出现 0?
以上是关于通过 TCP 发送/接收文件 [重复]的主要内容,如果未能解决你的问题,请参考以下文章