在第三篇里已经实现了文件的传输,但是在第三篇里,传输的文件是用一个包传过去的,如果文件大点的话,就无法实现了,今天我们来讲如何将大文件分包来处理。既然一个大文件不能一次传,那就要多次传了,既然是多次,那就要分包了。先把demo贴出,程序中都有注释。
服务端:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using System.IO; namespace FileReceiveControl{ public class FileOutPackets { public void GetFileOutPackets() { try { Console.WriteLine( " this is server " ); int Port = 8001 ; IPEndPoint ipep = new IPEndPoint(IPAddress.Any, Port); EndPoint ep = (EndPoint)ipep; Socket sc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); sc.Bind(ep); IPEndPoint ipepClient = new IPEndPoint(IPAddress.Any, 0 ); EndPoint epClient = (EndPoint)ipepClient; int Rec; byte [] Bytes = new byte [ 1024 ]; // =====获取文件名 Rec = sc.ReceiveFrom(Bytes, ref epClient); string FileName = Encoding.ASCII.GetString(Bytes, 0 , Rec); // =====向客服端 发送接收到的信号 Bytes = Encoding.ASCII.GetBytes( " 1 " ); sc.SendTo(Bytes, epClient); // ======获取文件 bytes 大小 Bytes = new byte [ 1024 ]; Rec = sc.ReceiveFrom(Bytes, ref epClient); // =====向客服端 发送接收到的信号 // Bytes = Encoding.ASCII.GetBytes("2"); // sc.SendTo(Bytes, epClient); // =======获取fs bytes总的大小 int FileByteLength = int .Parse(Encoding.ASCII.GetString(Bytes, 0 , Rec)); // =======获取总的包数量 Bytes = new byte [ 1024 ]; Rec = sc.ReceiveFrom(Bytes, ref epClient); // =======获取总的包数量 int PacketNum = int .Parse(Encoding.ASCII.GetString(Bytes, 0 , Rec)); Console.WriteLine( " packetNum is " + PacketNum); // ====获取最后一个包的大小 Bytes = new byte [ 1024 ]; Rec = sc.ReceiveFrom(Bytes, ref epClient); int FinalPacketSize = int .Parse(Encoding.ASCII.GetString(Bytes, 0 , Rec)); string TempPath = @" E:\ " + FileName + " .temp " ; FileStream fs = new FileStream(TempPath, FileMode.OpenOrCreate, FileAccess.Write); // ======循环 接收 for ( int i = 0 ; i < PacketNum; i ++ ) { byte [] Data = new byte [ 8192 ]; Rec = sc.ReceiveFrom(Data, ref epClient); fs.Write(Data, 0 , 8192 ); fs.Flush(); Console.WriteLine( " this is " + (i + 1 ) + " packet " ); } if (FinalPacketSize != 0 ) { byte [] data = new byte [FinalPacketSize]; Rec = sc.ReceiveFrom(data, ref epClient); fs.Write(data, 0 , FinalPacketSize); fs.Flush(); } fs.Close(); sc.Close(); FileStream FsMove = new FileStream(TempPath, FileMode.Open, FileAccess.Read); string Path = TempPath.Remove(TempPath.Length - 5 , 5 ); byte [] ByteFile = new byte [FsMove.Length]; FsMove.Read(ByteFile, 0 , ( int )FsMove.Length); File.WriteAllBytes(Path, ByteFile); FsMove.Close(); File.Delete(TempPath); Console.WriteLine( " receive is over " ); // ===========死循环 方便调试 避免直接退出 while ( true ) { } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } }}
客户端:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; namespace FileDistributeControl{ public class FileOutPackets { public void GetFileOutPackets() { Console.WriteLine( " this is client " ); int Port = 8001 ; string Ip = " 192.168.1.20 " ; IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(Ip), Port); EndPoint ep = (EndPoint)ipep; Socket sc = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp); string path = @" F:\1.jpg " ; FileInfo fino = new FileInfo(path); IPEndPoint ipepClient = new IPEndPoint(IPAddress.Any, 0 ); EndPoint epClient = (EndPoint)ipepClient; int Rec,Rtn; byte [] Bytes = new byte [ 1024 ]; // =========发送 文件名 sc.SendTo(Encoding.ASCII.GetBytes(fino.Name),ep); Rec = sc.ReceiveFrom(Bytes, ref epClient); Rtn = int .Parse(Encoding.ASCII.GetString(Bytes, 0 ,Rec)); if (Rtn == 1 ) { Console.WriteLine( " this file name send successful " ); FileStream fs = new FileStream(path,FileMode.Open,FileAccess.Read); // =======取得最后一个数据包前的数据包总数 (int)将一个浮点数 转整型,只会四舍,不会五入 // =======1k==1024B==1024*8b 1k等于2的10次方字节,一个字节等于8位 int PacketNum = ( int )(fs.Length / ( long ) 8192 ); int EndPacket = ( int )(fs.Length - PacketNum * 8192 ); // =======最后一个包有可能是0 int TotalPacket; if (EndPacket == 0 ) { TotalPacket = PacketNum; } else { TotalPacket = PacketNum + 1 ; } // =======发送总 的数据包 etc sc.SendTo(Encoding.ASCII.GetBytes(fs.Length.ToString()), ep); sc.SendTo(Encoding.ASCII.GetBytes(PacketNum.ToString()), ep); sc.SendTo(Encoding.ASCII.GetBytes(EndPacket.ToString()),ep); // =======循环发送 Console.WriteLine( " packetNum is " + PacketNum); for ( int i = 0 ; i < PacketNum; i ++ ) { byte [] data = new byte [ 8192 ]; fs.Read(data, 0 , 8192 ); sc.SendTo(data,ep); Console.WriteLine( " this is " + (i + 1 ) + " packet " ); Thread.Sleep( 300 ); } Console.WriteLine( " this for is over " ); // =======发送最后一个包 if (EndPacket != 0 ) { byte [] finallData = new byte [EndPacket]; fs.Read(finallData, 0 ,EndPacket); sc.SendTo(finallData,ep); Console.WriteLine( " this is final packet " ); } Console.WriteLine( " send over " ); } else { // =======返回值不等于1 重新发送 sc.SendTo(Encoding.ASCII.GetBytes(fino.Name),ep); } while ( true ) { } } }} 这样就可以把一个大文件分成很多个包来进行发送了。这里需要注意的是,循环发送的时候需要休眠段时间,如果没有sleep这条语句,那么在服务端无法完整的收完每一个包。至于为什么一次性发完无法收取完,我现在也解释不了,在研究中...希望下一遍的时候可以解决这些问题..
转载于:https://www.cnblogs.com/_fyz/archive/2011/05/10/2042194.html