通过TCP发送/接收文件 [英] Send / receive file over TCP

查看:137
本文介绍了通过TCP发送/接收文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:
TcpClient通过网络发送数据和接收数据
循环直到TcpClient响应完全读取

Possible Duplicate:
TcpClient send data and receive data over network
Loop until TcpClient response fully read

我正在尝试通过TCP将文件从服务器发送到客户端.

I am trying to send a file from a server to a client over TCP.

服务器端代码,正在发送文件:

Server-side code, sending file:

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();

客户端代码,接收文件:

Client-side code, receive file:

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();

有人可以指出我做错了什么吗?

Can someone point where I am getting it wrong ?

该文件具有1036 kb,仅发送1032 kb,然后卡住,它将不会在客户端的while循环中消失.

The file has 1036 kb, and it sends only 1032 kb and then gets stuck it won't get out the while loop on the client-side.

此外,如果我关闭服务器并非常快地打开它,它将发送最后一个字节,并且文件将完全发送. (此文件会完美打开)

Also if I close the server and open it really quick it sends the last bytes and the files sends completely. (this file opens perfectly)

我认为这是服务器端的一个问题,它没有发送所有字节,而是发送原因和位置...

I think it`s a problem on the server side not sending all the bytes but why and where...

推荐答案

从服务器端代码开始,这是一个问题:

Well this is a problem in your server-side code to start with:

fs.Read(data,0, data.Length);

您将忽略Read返回的值. 从不这样做.使用FileStream,您可能还可以,但是我个人还是不相信它.如果您使用的是.NET 4,则无论如何都不需要这样做-只需使用Stream.CopyTo.

You're ignoring the value returned by Read. Never do that. With FileStream you're possibly okay, but I personally wouldn't trust it anyway. If you're using .NET 4, you don't need to do this anyway - just use Stream.CopyTo.

在客户端代码上,最大的初始问题是您正在UI线程上执行所有这些操作.这是一个糟糕的主意-如果Read调用被阻止,则在出现网络故障时UI会冻结.

On the client-side code, your biggest initial problem is that you're doing all of this on the UI thread. That's a terrible idea - the UI will freeze if there's a network glitch, as the Read call is blocking.

同样,只需使用Stream.CopyTo,但要在后台线程中进行.

Again, just use Stream.CopyTo, but do it in a background thread.

此外,在所有所有情况下,对流使用using语句,以便无论发生什么情况都可以干净地将其关闭.

Additionally, in all of these cases, use a using statement for the streams, so that you close them cleanly whatever happens.

这只是一般卫生.现在,为什么要挂...

That's all just general hygiene. Now, as for why you're hanging...

...您没有在服务器端关闭网络流.因此,您永远不会到达客户端流的 end .如果只需要对单个文件使用连接,那么答案很简单:只需在服务器端关闭连接即可.

... you're not closing the network stream on the server side. Therefore you never reach the end of the stream on the client side. If you only need to use the connection for a single file, then the answer is simple: just close the connection on the server side.

但是,如果需要对多个文件使用相同的连接,则需要更多协议-需要某种方式来指示数据结束.共有三种常见的实现方式:

If, however, you need to use the same connection for multiple files, then you need more protocol - you need to some way of indicating the end of the data. There are three common ways of doing that:

  • 在数据本身之前写出数据的长度,然后在读取侧,先读取长度,然后读取那么多字节,如果流在完成之前完成,则失败.这要求您在开始写入之前知道要写入多少数据.
  • 使用一个数据结尾"标记,您可以在读取侧进行检测;通常这很痛苦,因为如果它出现在文本本身中,则需要转义该标记.
  • 第一种方法的一种变体,您一次写入一个长度为前缀的块,然后是一个零长度的块以指示数据结束".这非常灵活,但是如果第一种方法确实对您有用,那么显然比第一种方法要多得多的工作.

这篇关于通过TCP发送/接收文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆