using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
namespace ClassLibrary
{
/// <summary>
/// 文件传输服务器
/// </summary>
public class FileTransferServer
{
/* 服务器接收文件Socket */
private static Socket ServerSocket;
/* 文件根目录 */
private static string ServerRoot;
/// <summary>
/// 初始化服务
/// </summary>
/// <param name="config">xml配置文件</param>
public static void Init(string config)
{
/* 加载配置文件 */
XmlDocument xml = new XmlDocument();
//xml.Load(Path.Combine(Environment.CurrentDirectory, "config/tcp.xml"));
xml.Load(config);
XmlNode Config = xml.SelectSingleNode("Config/FileServer");
IPAddress ListenIP = IPAddress.Parse(Config.Attributes["ListenIP"].Value);
int ListenPort = Convert.ToInt32(Config.Attributes["ListenPort"].Value);
ServerRoot = Environment.CurrentDirectory; // 默认当前目录
/* 开始监听 */
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServerSocket.Bind(new IPEndPoint(ListenIP, ListenPort)); //绑定IP地址:端口
ServerSocket.Listen(10); //设定最多10个排队连接请求
Thread t = new Thread(ListenClientConnect);
t.Start();
}
private static void ListenClientConnect()
{
while (true)
{
if (ServerSocket != null)
{
try
{
Socket client = ServerSocket.Accept();
Thread th = new Thread(Handle);
th.Start(client);
}
catch
{
break;
}
}
}
}
private static void Handle(Object clientSocket)
{
Socket client = clientSocket as Socket;
// 获取头部协议
string header = ReceiveHeader(client);
Console.WriteLine(string.Format("{0} 请求 {1}",client.RemoteEndPoint.ToString() ,header));
// TODO 添加其它协议
switch (header.Substring(0, 3))
{
case "PUT":
string filename = header.Substring(4);
PutFile(client, filename);
break;
case "GET":
string fullPath = header.Substring(4);
GetFile(client, fullPath);
break;
default:
Console.WriteLine("We can not suppose this");
client.Close();
break;
}
}
/// <summary>
/// 接收远程文件
/// </summary>
/// <param name="client"></param>
/// <param name="filename"></param>
public static void PutFile(Socket client, string filename)
{
/* 创建一个新文件 */
string extension = Path.GetExtension(filename).Substring(1);
string fullPath = Path.Combine(ServerRoot, extension, DateTime.Now.ToString("yyyyMMddHHmmss-ffff") + "." + extension);
if (!Directory.Exists(Path.GetDirectoryName(fullPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
}
FileStream fileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
/* 循环接收 */
byte[] recvBuffer = new byte[1024];
while (true)
{
int length = client.Receive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None);
if (length == 0)
{
recvBuffer = null;
break;
}
fileStream.Write(recvBuffer, 0, length);//将接收到的数据包写入到文件流对象
}
client.Shutdown(SocketShutdown.Receive);
fileStream.Close();
//发送文件名到服务端
byte[] sendBuffer = System.Text.Encoding.Unicode.GetBytes(fullPath.Replace(ServerRoot, "").Substring(1));
client.Send(sendBuffer, 0, sendBuffer.Length, SocketFlags.None);
client.Shutdown(SocketShutdown.Send);
client.Close();
}
public static void GetFile(Socket client, string fullPath)
{
client.Shutdown(SocketShutdown.Receive);
/* 文件不存在 */
string path = Path.Combine(ServerRoot, fullPath);
if (!File.Exists(path))
{
client.Close();
return;
}
FileStream fileStream = File.OpenRead(path); // 文件流
/* 开始循环发送数据包 */
byte[] sendBuffer = new byte[1024]; //数据包
while (true)
{
int length = fileStream.Read(sendBuffer, 0, sendBuffer.Length);
if (length == 0)
{
break;
}
client.Send(sendBuffer, 0, length, SocketFlags.None);
}
client.Shutdown(SocketShutdown.Send);
client.Close();
fileStream.Close(); //关闭文件流
}
/// <summary>
/// 获取头部协议
/// </summary>
/// <param name="socket"></param>
/// <returns></returns>
private static string ReceiveHeader(Socket socket)
{
byte[] recvBuffer = new byte[256];
socket.Receive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None);
string header = System.Text.Encoding.Unicode.GetString(recvBuffer).Trim('\0');
return header;
}
/// <summary>
/// 退出
/// </summary>
public static void Exit()
{
ServerSocket.Shutdown(SocketShutdown.Both);
ServerSocket.Close();
ServerSocket = null;
}
}
/// <summary>
/// 文件传输客户端
/// </summary>
public class FileTransferClient
{
private static string IP = "127.0.0.1";
private static int Port = 6854;
/// <summary>
/// 初始化服务器连接配置
/// </summary>
/// <param name="config">xml配置文件</param>
public static void Init(string config)
{
/* 加载配置文件 */
XmlDocument xml = new XmlDocument();
//xml.Load(Path.Combine(Environment.CurrentDirectory, "config/tcp.xml"));
xml.Load(config);
XmlNode Config = xml.SelectSingleNode("Config/FileServer");
IP = Config.Attributes["ListenIP"].Value;
Port = Convert.ToInt32(Config.Attributes["ListenPort"].Value);
}
/// <summary>
/// 发送文件至服务器
/// </summary>
/// <param name="fullPath">即将发送的本地文件</param>
/// <returns>远程文件路径(相对于文件服务器根目录)</returns>
public static string SendFile(string fullPath)
{
// 连接服务器
Socket client = ConnectServer(IP, Port);
// 发送头部协议
string header = "PUT:" + Path.GetFileName(fullPath);
SendHeader(client, header);
FileStream fileStream = File.OpenRead(fullPath); // 文件流
/* 开始循环发送数据包 */
byte[] sendBuffer = new byte[1024]; //数据包
while (true)
{
int length = fileStream.Read(sendBuffer, 0, sendBuffer.Length);
if (length == 0)
{
break;
}
client.Send(sendBuffer, 0, length, SocketFlags.None);
}
client.Shutdown(SocketShutdown.Send);
fileStream.Close(); //关闭文件流
/* 获取服务器存储的文件名 */
string filename = string.Empty;
byte[] recvBuffer = new byte[1024];
int len = client.Receive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None);
if (len != 0)
{
filename = System.Text.Encoding.Unicode.GetString(recvBuffer.Take(len).ToArray());
}
Console.WriteLine(string.Format("完成上传成功,服务器返回新文件:{0}", filename));
client.Shutdown(SocketShutdown.Receive);
client.Close();
return filename;
}
/// <summary>
/// 从服务器获取文件
/// </summary>
/// <param name="remoteFile">远程文件路径(相对于文件服务器根目录)</param>
/// /// <param name="localFile">保存的本地文件</param>
public static void GetFile(string remoteFile, string localFile)
{
// 连接服务器
Socket client = ConnectServer(IP, Port);
// 发送头部协议
string header = "GET:" + remoteFile;
SendHeader(client, header);
client.Shutdown(SocketShutdown.Send);
//创建一个新文件
bool recv = false; // 是否接收到文件数据
// TODO: 用特殊的位标志标识文件接收情况
FileStream fileStream = new FileStream(localFile, FileMode.Create, FileAccess.Write);
byte[] recvBuffer = new byte[1024];
while (true)
{
int length = client.Receive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None);
if (length == 0)
{
recvBuffer = null;
break;
}
fileStream.Write(recvBuffer, 0, length);//将接收到的数据包写入到文件流对象
recv = true;
}
client.Shutdown(SocketShutdown.Receive);
client.Close();
fileStream.Close();
/* 未接收到任何文件数据 */
if (recv == false)
{
File.Delete(localFile);
return;
}
Console.WriteLine("文件获取成功,保存到本地:"+localFile);
}
/// <summary>
/// 连接服务器
/// </summary>
/// <returns></returns>
private static Socket ConnectServer(string IP, int Port)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建套接字
try
{
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(IP), Port); //指向远程服务端节点
client.Connect(ep);
}
catch
{
Console.WriteLine("连接文件服务器失败");
}
return client;
}
/// <summary>
/// 发送头部协议
/// </summary>
/// <param name="socket"></param>
/// <param name="header"></param>
private static void SendHeader(Socket socket, string header)
{
byte[] sendBuffer = new byte[256];
System.Text.Encoding.Unicode.GetBytes(header).CopyTo(sendBuffer, 0);
socket.Send(sendBuffer, 0, sendBuffer.Length, SocketFlags.None);
}
}
}
服务端使用
Console.WriteLine("===================== 开启文件服务器 =====================");
FileTransferServer.Init(Path.Combine(Environment.CurrentDirectory, "config/tcp.xml"));