类似的博文很多了,但是质量良莠不齐,有的可用性、可移植性比较差。这段代码我调试了两天,运行起来性能、稳定型不错。要求不高的中、小程序直接作为Dll类库引用没问题。
发篇博文用来记录,也好分享给大家成果。此段代码仍有很多可以提高的地方,希望算是抛砖引玉。
需求:
服务端(1):能够持续监听,并查收文件。
客户端(N):能够连接服务器发送文件。
使用效果测试:局域网内,4G的单个文件传输没问题。稳定性还是有保障的,而且内存消耗也比较稳定、可控。
现有代码可以完善的问题一:服务端无法实现多个文件同时接收,请教各位高手给个思路?
public static class FileSender
{
private const int BufferSize = 1024;
public static void Send(IPEndPoint ip, string fullPathFileName)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(ip);
using (FileStream reader = new FileStream(fullPathFileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
//发送文件长度
long send = 0L, length = reader.Length;
byte[] byteArrayLength = BitConverter.GetBytes(length);
sock.Send(byteArrayLength);
///发送文件名
string fileName = Path.GetFileName(fullPathFileName);
byte[] bufferFileName = Encoding.Default.GetBytes(fileName);
sock.Send(bufferFileName);
//sock.Send(BitConverter.GetBytes());
Console.WriteLine("Sending file:" + fileName + ";Size:" + length + "Byte;Please wait...");
byte[] buffer = new byte[BufferSize];
int read, sent;
//断点发送 在这里判断设置reader.Position即可
while ((read = reader.Read(buffer, 0, BufferSize)) != 0)
{
sent = 0;
while ((sent += sock.Send(buffer, sent, read, SocketFlags.None)) < read)
{
send += (long)sent;
//Console.WriteLine("Sent " + send + "/" + length + ".");//进度
}
}
Console.WriteLine("Send finish.");
}
}
public static bool ReceiverBusying = false;
public static void Receive(int port, string path)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Bind(ip);
sock.Listen(100);
while (true)
{
Socket client = sock.Accept();
ReceiverBusying = true;
byte[] buffer = new byte[BufferSize];
client.Receive(buffer);
long receive = 0L, length = BitConverter.ToInt64(buffer,0);
buffer = new byte[BufferSize];
int receivedNum=client.Receive(buffer);
string fileName = Encoding.Default.GetString(buffer, 0, receivedNum);
Console.WriteLine("Receiving file:" + fileName + ";Size:" + length + "Byte; Please wait...");
string targetPathFileName;
try
{
///完整文件名
targetPathFileName = Path.Combine(path, fileName);
}
catch//用当前时间.xml
{
targetPathFileName = Path.Combine(path, DateTime.Now.ToString("yyyyMMddHHmmss") + ".xml");
}
using (FileStream writer = new FileStream(targetPathFileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
int received;
//断点接受 在这里判断设置writer.Position即可
while (receive < length)
{
received = client.Receive(buffer);
writer.Write(buffer, 0, received);
writer.Flush();
receive += (long)received;
//Console.WriteLine("Received " + receive + "/" + length + ".");//进度
}
}
ReceiverBusying = false;
Console.WriteLine("Receive finish.");
}
}
/// <summary>
/// 地址为默认路径
/// </summary>
/// <param name="ip"></param>
public static void Receive(int port)
{
string path = AppDomain.CurrentDomain.BaseDirectory;
Receive(port, path);
}
/// 比较两个字节数组是否相等
/// </summary>
/// <param name="b1">byte数组1</param>
/// <param name="b2">byte数组2</param>
/// <returns>是否相等</returns>
public static bool PasswordEquals(byte[] b1, byte[] b2)
{
if (b1 == null || b2 == null) return false;
if (b1.Length != b2.Length) return false;
for (int i = 0; i < b1.Length; i++)
if (b1[i] != b2[i])
return false;
return true;
}
}