可能重复:
TcpClient send data and receive data over network
Loop 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循环。
此外,如果我关闭服务器并快速打开它,它会发送最后一个字节并且文件完全发送。 (此文件打开完美)
我认为服务器端的问题不是发送所有字节而是为什么以及在哪里......
答案 0 :(得分:6)
这是您的服务器端代码中的问题:
fs.Read(data,0, data.Length);
您忽略了Read
返回的值。 从不那样做。使用FileStream
你可能可以,但我个人不会相信它。如果您使用的是.NET 4,则无论如何都不需要这样做 - 只需使用Stream.CopyTo
。
在客户端代码上,您最大的初始问题是您在UI线程上执行所有这些操作。这是一个糟糕的主意 - 如果网络出现故障,用户界面将会冻结,因为Read
呼叫正在阻止。
再次,只需使用Stream.CopyTo
,但在后台线程中执行。
此外,在这些情况的所有中,对流使用using
语句,以便无论发生什么都干净地关闭它们。
这就是一般卫生。现在,至于为什么你要挂......
...您没有关闭服务器端的网络流。因此,您永远不会在客户端访问流的 end 。如果您只需要为单个文件使用连接,那么答案很简单:只需关闭服务器端的连接。
但是,如果您需要为多个文件使用相同的连接,那么您需要更多协议 - 您需要某种方式来指示数据的结束。有三种常见的方法: