C# Socket傳輸大文件

1.基礎類TransferFiles,client和server都需要

using System;
using System.Collections.Generic;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;


namespace Server
{
    public class TransferFiles
    {
        public static int SendData(Socket s, byte[] data)
        {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;

            while (total < size)
            {
                sent = s.Send(data, total, dataleft, SocketFlags.None);
                total += sent;
                dataleft -= sent;
            }

            return total;
        }


        public static byte[] ReceiveData(Socket s, int size)
        {
            int total = 0;
            int dataleft = size;
            byte[] data = new byte[size];
            int recv;
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);
                if (recv == 0)
                {
                    data = null;
                    break;
                }

                total += recv;
                dataleft -= recv;
            }
            return data;
        }

        public static int SendVarData(Socket s, byte[] data)
        {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;
            byte[] datasize = new byte[4];

            try
            {
                datasize = BitConverter.GetBytes(size);
                sent = s.Send(datasize);

                while (total < size)
                {
                    sent = s.Send(data, total, dataleft, SocketFlags.None);
                    total += sent;
                    dataleft -= sent;
                }

                return total;
            }
            catch
            {
                return 3;

            }
        }

        public static byte[] ReceiveVarData(Socket s)
        {
            int total = 0;
            int recv;
            byte[] datasize = new byte[4];
            recv = s.Receive(datasize, 0, 4, SocketFlags.None);
            int size = BitConverter.ToInt32(datasize, 0);
            int dataleft = size;
            byte[] data = new byte[size];
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);
                if (recv == 0)
                {
                    data = null;
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
        }
    }
}


2.Server端

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Configuration;

namespace Server
{
    public static class FileServer
    {
        private static Socket serverSocket;
        public static void Init()
        {
            //服務器IP地址
            IPAddress ip = IPAddress.Parse(ConfigurationManager.AppSettings["ListenIP"]);
            int myProt = Convert.ToInt32(ConfigurationManager.AppSettings["ListenFilePort"]);
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(new IPEndPoint(ip, myProt));  //綁定IP地址:端口
            serverSocket.Listen(10);    //設定最多10個排隊連接請求
            Console.WriteLine("啓動監聽{0}成功", serverSocket.LocalEndPoint.ToString());
            //通過Clientsoket發送數據
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
        }
        public static void Exit()
        {
            serverSocket.Close();
            serverSocket = null;
        }
        private static void ListenClientConnect()
        {
            while (true)
            {
                if (serverSocket != null)
                {
                    try
                    {
                        Socket clientSocket = serverSocket.Accept();
                        Thread receiveThread = new Thread(Create);
                        receiveThread.Start(clientSocket);
                    }
                    catch
                    {
                        break;
                    }
                }
            }
        }
        public static void Create(object clientSocket)
        {
            Socket client = clientSocket as Socket;
            //獲得客戶端節點對象
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;            

            //獲得[文件名]   
            string SendFileName = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));

            //檢查是否使用本地媒體庫
            if (SocketServer.useLocal)
            {
                //關閉套接字   
                client.Close();
                return;
            }

            //獲得[包的大小]   
            string bagSize = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));

            //獲得[包的總數量]   
            int bagCount = int.Parse(System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client)));

            //獲得[最後一個包的大小]   
            string bagLast = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));


            string fullPath = Path.Combine(Environment.CurrentDirectory,SendFileName);
            //創建一個新文件   
            FileStream MyFileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write);

            //已發送包的個數   
            int SendedCount = 0;
            while (true)
            {

                byte[] data = TransferFiles.ReceiveVarData(client);
                if (data.Length == 0)
                {
                    break;
                }
                else
                {                    
                    SendedCount++;
                    //將接收到的數據包寫入到文件流對象   
                    MyFileStream.Write(data, 0, data.Length);
                    //顯示已發送包的個數     

                }
            }
            //關閉文件流   
            MyFileStream.Close();
            //關閉套接字   
            client.Close();
            SocketServer.pForm.ShowMessageBox(SendFileName + "接收完畢!");
        }
    }
}

3.Client端

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

namespace Client
{
    public static class FileClient
    {
        public static bool SendFile(string IP,int Port,string fullPath)
        {
            //創建一個文件對象
            FileInfo EzoneFile = new FileInfo(fullPath);
            //打開文件流
            FileStream EzoneStream = EzoneFile.OpenRead();

            //包的大小
            int PacketSize = 10000;

            //包的數量
            int PacketCount = (int)(EzoneStream.Length / ((long)PacketSize));

            //最後一個包的大小
            int LastDataPacket = (int)(EzoneStream.Length - ((long)(PacketSize * PacketCount)));

            //指向遠程服務端節點
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(IP), Port);

            //創建套接字
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //連接到發送端
            try
            {
                client.Connect(ipep);
            }
            catch
            {
                Debug.WriteLine("連接服務器失敗!");
                return false;
            }
            //獲得客戶端節點對象
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;


            //發送[文件名]到客戶端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(EzoneFile.Name));

            //發送[包的大小]到客戶端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(PacketSize.ToString()));

            //發送[包的總數量]到客戶端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(PacketCount.ToString()));

            //發送[最後一個包的大小]到客戶端
            TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(LastDataPacket.ToString()));

            bool isCut = false;
            //數據包
            byte[] data = new byte[PacketSize];
            //開始循環發送數據包
            for (int i = 0; i < PacketCount; i++)
            {
                //從文件流讀取數據並填充數據包
                EzoneStream.Read(data, 0, data.Length);
                //發送數據包
                if (TransferFiles.SendVarData(client, data) == 3)
                {                    
                    isCut = true;
                    return false;
                    break;
                }

            }

            //如果還有多餘的數據包,則應該發送完畢!
            if (LastDataPacket != 0)
            {
                data = new byte[LastDataPacket];
                EzoneStream.Read(data, 0, data.Length);
                TransferFiles.SendVarData(client, data);
            }

            //關閉套接字
            client.Close();
            //關閉文件流
            EzoneStream.Close();
            if (!isCut)
            {
                return true;
            }
            return false;
        }
    }
}




發佈了16 篇原創文章 · 獲贊 9 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章