C# socket编程第四篇
时间:2011-05-10 来源:comeonfyz
在第三篇里已经实现了文件的传输,但是在第三篇里,传输的文件是用一个包传过去的,如果文件大点的话,就无法实现了,今天我们来讲如何将大文件分包来处理。既然一个大文件不能一次传,那就要多次传了,既然是多次,那就要分包了。先把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;这样就可以把一个大文件分成很多个包来进行发送了。这里需要注意的是,循环发送的时候需要休眠段时间,如果没有sleep这条语句,那么在服务端无法完整的收完每一个包。至于为什么一次性发完无法收取完,我现在也解释不了,在研究中...希望下一遍的时候可以解决这些问题..
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)
{ }
}
}
}
相关阅读 更多 +