C#文件服务器

@bruce  November 3, 2019
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"));

添加新评论