Socket發送文件


1.Net.cs
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;

namespace SocketIM
{
    ////// Net : 提供靜態方法,對常用的網絡操作進行封裝
    public class Net
    {
        public class ObjectState
        {
            public string fileName { get; set; }
            public Socket workSocket { get; set; }
            public Thread workThread { get; set; }
        }
        private Net()
        {
        }


        ////// 向遠程主機發送數據
        //////要發送數據且已經連接到遠程主機的 Socket///待發送的數據///發送數據的超時時間,以秒為單位,可以精確到微秒///0:發送數據成功;-1:超時;-2:發送數據出現錯誤;-3:發送數據時出現異常////// 當 outTime 指定為-1時,將一直等待直到有數據需要發送
        public static int SendData(Socket socket, byte[] buffer, int outTime)
        {
            if (socket == null || socket.Connected == false)
            {
                throw new ArgumentException("參數socket 為null,或者未連接到遠程計算機");
            }
            if (buffer == null || buffer.Length == 0)
            {
                throw new ArgumentException("參數buffer 為null ,或者長度為 0");
            }

            int flag = 0;
            try
            {
                int totalLen = buffer.Length;
                int sndLen = 0;

                while (true)
                {
                    if ((socket.Poll(outTime * 100, SelectMode.SelectWrite) == true))
                    {        // 收集了足夠多的傳出數據后開始發送
                        sndLen = socket.Send(buffer, sndLen, totalLen, SocketFlags.None);
                        totalLen -= sndLen;
                        if (totalLen == 0)
                        {                                        // 數據已經全部發送
                            flag = 0;
                            break;
                        }
                        else
                        {
                            if (sndLen > 0)
                            {                                    // 數據部分已經被發送continue;
                            }
                            else
                            {                                                // 發送數據發生錯誤
                                flag = -2;
                                break;
                            }
                        }
                    }
                    else
                    {                                                        // 超時退出
                        flag = -1;
                        break;
                    }
                }
            }
            catch (SocketException e)
            {

                flag = -3;
            }
            return flag;
        }


        ////// 向遠程主機發送文件
        //////要發送數據且已經連接到遠程主機的 socket///待發送的文件名稱///文件發送時的緩沖區大小///發送緩沖區中的數據的超時時間///0:發送文件成功;-1:超時;-2:發送文件出現錯誤;-3:發送文件出現異常;-4:讀取待發送文件發生錯誤////// 當 outTime 指定為-1時,將一直等待直到有數據需要發送
        public static int SendFile(string ip, int port, string fileName, int maxBufferLength, int outTime)
        {
            IPAddress address = IPAddress.Parse(ip);
            IPEndPoint endpoint = new IPEndPoint(address, port);
            //創建服務端負責監聽的套接字,參數(使用IPV4協議,使用流式連接,使用TCO協議傳輸數據)
            Thread.Sleep(1500);
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Connect(endpoint);
            if (socket.Connected)
            {
                Console.WriteLine(socket.RemoteEndPoint + "連接成功");
            }
            if (fileName == null || maxBufferLength <= 0)
            {
                throw new ArgumentException("待發送的文件名稱為空或發送緩沖區的大小設置不正確.");
            }
            int flag = 0;
            try
            {
                FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                long fileLen = fs.Length;                        // 文件長度
                long totalLen = fileLen;                            // 未讀取部分
                int readLen = 0;                                // 已讀取部分
                byte[] buffer = null;

                if (fileLen <= maxBufferLength)
                {            /* 文件可以一次讀取*/
                    buffer = new byte[fileLen];
                    readLen = fs.Read(buffer, 0, (int)fileLen);
                    flag = SendData(socket, buffer, outTime);
                }
                else
                {
                    /* 循環讀取文件,並發送 */
                    while (totalLen != 0)
                    {
                        if (totalLen < maxBufferLength)
                        {
                            buffer = new byte[totalLen];
                            readLen = fs.Read(buffer, 0, Convert.ToInt32(totalLen));
                        }
                        else
                        {
                            buffer = new byte[maxBufferLength];
                            readLen = fs.Read(buffer, 0, maxBufferLength);
                        }
                        if ((flag = SendData(socket, buffer, outTime)) < 0)
                        {
                            break;
                        }
                        totalLen -= readLen;
                    }
                }
                fs.Flush();
                fs.Close();
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
            catch (IOException e)
            {

                flag = -4;
            }
            if (flag == 0)
            {
                Console.WriteLine(fileName + "文件發送成功");
                socket.Close();
                Console.WriteLine("連接關閉");
            }
            else
            {
                Console.WriteLine(fileName + "文件發送失敗,i=" + flag);
            }
            return flag;
        }
        private static void WatchConnecting(object info)
        {
            ObjectState state = (ObjectState)info;
            Socket socketWatch = state.workSocket;
            while (true)//持續不斷的監聽客戶端的請求            
            {
                //開始監聽 客戶端連接請求,注意:Accept方法,會阻斷當前的線程
                Socket connection = socketWatch.Accept();
                
                
                if (connection.Connected)
                {
                    
                    //創建通信線程
                    Thread thradRecMsg = new Thread(RecMsg);
                    state.workSocket = connection;
                    state.workThread = thradRecMsg;
                    thradRecMsg.IsBackground = true;
                    thradRecMsg.Start(state);

                }
            }

        }
        ////// 接收消息
        private static void RecMsg(object socketClientPara)
        {

            ObjectState state = (ObjectState)socketClientPara;
            string fileName = state.fileName;//$@"d:HQ.dat";//獲得用戶保存文件的路徑
            Socket socketClient = state.workSocket;
            FileStream fs = null;
            while (true)
            {
                //定義一個接受用的緩存區(100M字節數組)
                //將接收到的數據存入arrMsgRec數組,並返回真正接受到的數據的長度   
                if (socketClient.Connected)
                {
                    try
                    {
                        //因為終端每次發送文件的最大緩沖區是512字節,所以每次接收也是定義為512字節
                        byte[] buffer = new byte[512];
                        int size = 0;
                        //統計實際文件大小
                        long len = 0;
                        //創建文件流,然后讓文件流來根據路徑創建一個文件
                        fs = new FileStream(fileName, FileMode.Append);
                        DateTime oTimeBegin = DateTime.Now;
                        //從終端不停的接受數據,然后寫入文件里面,只到接受到的數據為0為止,則中斷連接
                        while ((size = socketClient.Receive(buffer, 0, buffer.Length, SocketFlags.None)) > 0)
                        {
                            fs.Write(buffer, 0, size);
                            len += size;
                        }
                        DateTime oTimeEnd = DateTime.Now;
                        TimeSpan oTime = oTimeEnd.Subtract(oTimeBegin);
                        fs.Flush();
                        fs.Close();
                   
                        socketClient.Shutdown(SocketShutdown.Both);
                        socketClient.Close();
                        Console.WriteLine("文件保存成功:" + fileName);
                        Console.WriteLine("接收文件用時:" + oTime.ToString() + ",文件大小:" + len / 1024 + "kb");
                    }
                    catch (Exception ex)
                    {
                        if (fs != null)
                        {
                            fs.Dispose();
                        }
                        if (File.Exists(fileName))
                        {
                            File.Delete(fileName);
                        }
                        Console.WriteLine(socketClient.RemoteEndPoint + "下線了");

                        break;
                    }
                }
                else
                {

                }
            }
        }


        public static void AcceptFile(string ip, int port, string fileName)
        {
            //創建服務端負責監聽的套接字,參數(使用IPV4協議,使用流式連接,使用Tcp協議傳輸數據)
            Socket socketListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socketListen.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            //獲取Ip地址對象
            IPAddress address = IPAddress.Parse(ip);
            //創建包含Ip和port的網絡節點對象
            IPEndPoint endpoint = new IPEndPoint(address, port);
            
            //將負責監聽的套接字綁定到唯一的Ip和端口上          
            socketListen.Bind(endpoint);
            //設置監聽隊列的長度
            socketListen.Listen(10);
            connectDone.Set();
            ObjectState state = new ObjectState();
            
            //創建負責監聽的線程,並傳入監聽方法
            Thread threadWatch = new Thread(WatchConnecting);
            state.fileName = fileName;
            state.workSocket = socketListen;
            state.workThread = threadWatch;
            threadWatch.IsBackground = true;//設置為后台線程
            threadWatch.Start(state);//開始線程

        }
        public static void CloseTcpSocket(Thread threadWatch, Socket socketWatch)
        {

            threadWatch.Abort();
            socketWatch.Close();
            Console.WriteLine("服務器關閉監聽");
        }
        public static ManualResetEvent connectDone = new ManualResetEvent(false);
        public static void FileMove(string ip, int port, string fromPath, string toPath)
        {

            AcceptFile(ip, port, toPath);
            connectDone.WaitOne();
            int i = SendFile(ip, port, fromPath, 512, 90000);
            Console.WriteLine("文件從" + fromPath + "" + toPath + "移動成功!!!!");
        }

    }
}
2.調用代碼
        private void button1_Click(object sender, EventArgs e)
        {
            //string topath = $@"d:HQ.dat";
            //string frompath = $@"e:\HQ.dat";
            //Net.FileMove("127.0.0.1", 11000, frompath,topath);
            string topath = $@"d:bb\HQ.dat";
            string frompath = $@"d:aa\HQ.dat";
            Net.FileMove("127.0.0.1", 11000, frompath, topath);
        }
       

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM