Socket传输大文件(发送与接收)

下载

Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Windows.Forms;


namespace SocketClient
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            SocketClient();
        }
        public static string serverIp = "127.0.0.1";//设置服务端IP
        public static int serverPort = 8888;//服务端端口
        public static Socket socketClient;//定义socket
        public static Thread threadClient;//定义线程
        public static byte[] result = new byte[1024];//定义缓存
        public static void SocketClient()
        {
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个socket的对象
            IPAddress ip = IPAddress.Parse(serverIp);//获取服务器IP地址
            IPEndPoint point = new IPEndPoint(ip, serverPort);//获取端口
            try
            {
                socketClient.Connect(point);//链接服务器IP与端口
                Console.WriteLine("连接服务器中.....");

            }
            catch (Exception)
            {
                Console.WriteLine("与服务器链接失败!!!");
                return;
            }
            Console.WriteLine("与服务器链接成功!!!");
            try
            {
                Thread.Sleep(1000);    //等待1秒钟  
                //通过 socketClient 向服务器发送数据
                string sendMessage = "已成功接到SocketClient发送的消息";//发送到服务端的内容
                byte[] send = Encoding.UTF8.GetBytes(sendMessage);//Encoding.UTF8.GetBytes()将要发送的字符串转换成UTF8字节数组
                byte[] SendMsg = new byte[send.Length + 1];//定义新的字节数组
                SendMsg[0] = 0;//将数组第一位设置为0,来表示发送的是消息数据  
                Buffer.BlockCopy(send, 0, SendMsg, 1, send.Length);//偏移复制字节数组
                socketClient.Send(SendMsg);  //将接受成功的消息返回给SocketServer服务器 
                Console.WriteLine("发送完毕:{0}", sendMessage);

            }                                                                                                                     
            catch
            {
                socketClient.Shutdown(SocketShutdown.Both);//禁止Socket上的发送和接受
                socketClient.Close();//关闭Socket并释放资源
            }
            //打开文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "选择要传的文件";
            ofd.InitialDirectory = @"E:IVSDown";
            //ofd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*";
            ofd.ShowDialog();
            //得到选择文件的路径
            string filePath = ofd.FileName;//获取文件的完整路径
            Console.WriteLine("发送的文件路径为:"+filePath);
            using (FileStream fsRead = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read))
            {
                //1. 第一步:发送一个文件,表示文件名和长度,让客户端知道后续要接收几个包来重新组织成一个文件
                string fileName = Path.GetFileName(filePath);
                Console.WriteLine("发送的文件名是:" + fileName);
                long fileLength = fsRead.Length;//文件长度
                Console.WriteLine("发送的文件长度为:"+fileLength);
                string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
                byte[] buffer = Encoding.UTF8.GetBytes(totalMsg); 
                byte[] newBuffer = new byte[buffer.Length + 1];
                newBuffer[0] = 2;
                Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);
                socketClient.Send(newBuffer);//发送文件前,将文件名和长度发过去
                //2第二步:每次发送一个1MB的包,如果文件较大,则会拆分为多个包
                byte[] Filebuffer = new byte[1024 * 1024 * 5];//定义1MB的缓存空间
                int readLength = 0;  //定义读取的长度
                bool firstRead = true;
                long sentFileLength = 0;//定义发送的长度
                while ((readLength = fsRead.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                {
                    sentFileLength += readLength;
                    //第一次发送的字节流上加个前缀1
                    if (firstRead)
                    {
                        byte[] firstBuffer = new byte[readLength + 1];
                        firstBuffer[0] = 1;//标记1,代表为文件
                        Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);
                        socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);
                        Console.WriteLine("第一次读取数据成功,在前面添加一个标记");
                        firstRead = false;
                        continue;
                    }
                    socketClient.Send(buffer, 0, readLength, SocketFlags.None);
                    Console.WriteLine("{0}: 已发送数据:{1}/{2}", socketClient.RemoteEndPoint, sentFileLength, fileLength);
                }
                fsRead.Close();
                Console.WriteLine("发送完成");
            }
            Console.ReadLine();
        }
    }

}

Server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Windows.Forms;

namespace SocketServer
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            SocketServer();
        }
        public static string serverIp = "127.0.0.1";//设置服务端IP
        public static int serverPort = 8888;//服务端端口
        public static Socket socketServer;//定义socket
        public static Thread threadWatch;//定义线程
        public static byte[] result = new byte[1024 * 1024 * 2];//定义缓存
        //public static string fileName;//获取文件名
        public static string filePath = "";//存储保存文件的路径
        public static void SocketServer()
        {
            socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个socket的对象
            IPAddress ip = IPAddress.Parse(serverIp);//获取服务器IP地址
            IPEndPoint point = new IPEndPoint(ip, serverPort);//获取端口
            try
            {
                socketServer.Bind(point);//绑定IP地址及端口
            }
            catch (Exception ex)
            {
                Console.WriteLine("绑定IP时出现异常:" + ex.Message);
                return;
            }
            socketServer.Listen(100);//开启监听并设定最多10个排队连接请求
            threadWatch = new Thread(WatchConnect);//创建一个监听进程
            threadWatch.IsBackground = true;//后台启动
            threadWatch.Start();//运行
            Console.WriteLine("服务器{0}监听启动成功!", socketServer.LocalEndPoint.ToString());
            Console.ReadLine();
        }
        public static void WatchConnect()
        {
            while (true)
            {
                Socket watchConnect = socketServer.Accept();//接收连接并返回一个新的Socket
                watchConnect.Send(Encoding.UTF8.GetBytes("服务器连接成功"));//在客户端显示"服务器连接成功"提示
                Thread threadwhat = new Thread(ReceiveMsg);//创建一个接受信息的进程
                threadwhat.IsBackground = true;//后台启动
                threadwhat.Start(watchConnect);//有传入参数的线程
            }
        }
        public static DateTime GetTime()
        {
            DateTime now = new DateTime();
            now = DateTime.Now;
            return now;
        }
        public static void ReceiveMsg(object watchConnect)
        {
            Socket socketServer = watchConnect as Socket;
            long fileLength = 0;//文件长度
            string recStr = null;//文件名
            while (true)
            {
                int firstRcv = 0;
                byte[] buffer = new byte[1024 * 1024 * 5];
                try
                {
                    //获取接受数据的长度,存入内存缓冲区,返回一个字节数组的长度
                    if (socketServer != null) firstRcv = socketServer.Receive(buffer);
                    if (firstRcv > 0)//大于0,说明有东西传过来
                    {
                        if (buffer[0] == 0)//0对应文字信息
                        {
                            string recMsg = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            Console.WriteLine("客户端接收到信息:" + socketServer.LocalEndPoint.ToString() + "
" + GetTime() + "
" + recMsg + "
");
                        }

                        if (buffer[0] == 1)//1对应文件信息
                        {
                            SaveFileDialog sfDialog = new SaveFileDialog();//创建SaveFileDialog实例
                            string spath = @"E:存放";//制定存储路径
                            string savePath = Path.Combine(spath, recStr);//获取存储路径及文件名
                            int rec = 0;
                            long recFileLength = 0;
                            bool firstWrite = true;
                            using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                            {
                                while (recFileLength < fileLength)
                                {
                                    if (firstWrite)
                                    {
                                        fs.Write(buffer, 1, firstRcv - 1);
                                        fs.Flush();
                                        recFileLength += firstRcv - 1;
                                        firstWrite = false;
                                    }
                                    else
                                    {
                                        rec = socketServer.Receive(buffer);
                                        fs.Write(buffer, 0, rec);
                                        fs.Flush();
                                        recFileLength += rec;
                                    }
                                    Console.WriteLine("{0}: 已接收数据:{1}/{2}", socketServer.RemoteEndPoint, recFileLength, fileLength);
                                }
                                fs.Close();
                            }
                            Console.WriteLine("保存成功!!!!");
                        }
                        if (buffer[0] == 2)//2对应文件名字和长度
                        {
                            string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            recStr = fileNameWithLength.Split('-').First();//获取文件名
                            Console.WriteLine("接收到的文件名为:" + recStr);
                            fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());//获取文件长度
                            Console.WriteLine("接收到的文件长度为:" + fileLength);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("系统异常..." + ex.Message);
                    break;
                }
            }

            //while (true)
            //{
            //    int num = -1;//初始化num
            //    string reveiceName;//定义字符串
            //    try
            //    {
            //        num = socketClient.Receive(result);//获取客户端信息
            //        reveiceName = Encoding.UTF8.GetString(result, 0, num);//把从0到num的字节变成String
            //    }
            //    catch (SocketException ex)
            //    {
            //        Console.WriteLine("异常:" + ex.Message + ", RemoteEndPoint: " + socketClient.RemoteEndPoint.ToString());
            //        break;
            //    }
            //    catch (Exception ex)
            //    {
            //        Console.WriteLine("异常:" + ex.Message);
            //        break;
            //    }

            //while (true)
            //{

            //try
            //{
            //    /// <summary>
            //    /// 存储大文件的大小
            //    /// </summary>
            //   long length = 0;
            //   long recive = 0; //接收的大文件总的字节数
            //    while (true)
            //    {
            //        byte[] buffer = new byte[1024 * 1024];
            //        int r = socketClient.Receive(buffer);
            //        Console.WriteLine("接受到的字符长度" + r);
            //        if (r == 0)
            //        {
            //            break;
            //        }
            //        Console.WriteLine("第二次的length长度为:" + length);
            //        if (length > 0)  //判断大文件是否已经保存完
            //        {
            //            //保存接收的文件
            //            using (FileStream fsWrite = new FileStream(filePath, FileMode.Append, FileAccess.Write))
            //            {
            //                Console.WriteLine("-----------------11111111111111111111111-----------------------------");
            //                fsWrite.Write(buffer, 0, r);
            //                length -= r; //减去每次保存的字节数
            //                Console.WriteLine("{0}: 已接收:{1}/{2}", socketClient.RemoteEndPoint, recive - length, recive);
            //                if (length <= 0)
            //                {
            //                    Console.WriteLine(socketClient.RemoteEndPoint + ": 接收文件成功");
            //                }
            //                continue;
            //            }
            //        }
            //        if (buffer[0] == 0) //如果接收的字节数组的第一个字节是0,说明接收的字符串信息
            //        {
            //            string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1);
            //            Console.WriteLine("*****************0000000000000000000000*********************");
            //            Console.WriteLine(socketClient.RemoteEndPoint.ToString() + ": " + strMsg);
            //        }
            //        else if (buffer[0] == 1) //如果接收的字节数组的第一个字节是1,说明接收的是文件
            //        {
            //            Console.WriteLine("++++++++++++++111111111111111111111+++++++++++++++++++");
            //            length = int.Parse(Encoding.UTF8.GetString(buffer, 1, r - 1));
            //            recive = length;
            //            Console.WriteLine("接收到的字节长度是多少呢:?" + length);
            //            SaveFileDialog sfd = new SaveFileDialog();
            //            sfd.Title = "保存文件";
            //            sfd.InitialDirectory = @"C:UsersAdministratorDesktop";
            //            //sfd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*";
            //            //如果没有选择保存文件路径就一直打开保存框
            //            SaveFileDialog save = new SaveFileDialog();//创建SaveFileDialog实例
            //            string spath = @"C:UsersadminDesktop";//制定存储路径
            //            filePath = Path.Combine(spath, fileName);//获取存储路径及文件名
            //        }
            //    }
            //}
            //catch { }

            //}
















            //try
            //{
            //    if (reveiceName[0] == 0)//判断数组第一个值,如果为0则说明传的是信息
            //    {
            //        fileName = Encoding.UTF8.GetString(result, 1, num - 1);//提取字节信息并转换成String
            //        Console.WriteLine("接收客户端的消息:{0}", fileName);
            //    }
            //    if (reveiceName[0] == 1)//判断数组第一个值,如果为1则说明传的是文件
            //    {
            //        SaveFileDialog save = new SaveFileDialog();//创建SaveFileDialog实例
            //        string spath = @"C:UsersadminDesktop";//制定存储路径
            //        string fullPath = Path.Combine(spath, fileName);//获取存储路径及文件名
            //        //FileStream filesave = new FileStream(fullPath, FileMode.Create, FileAccess.Write);//创建文件流,用来写入数据
            //        //filesave.Write(result, 1, num - 1);//将数据写入到文件中
            //        //filesave.Close();
            //        //Console.WriteLine("保存成功!!!");
            //        //**************************************************************************************************
            //        while (true)
            //        {
            //            byte[] buffer = new byte[1024 * 1024];
            //            int r = socketClient.Receive(buffer);
            //            Console.WriteLine("从客户端接收到的字节数:"+r);
            //            //string leng = Encoding.UTF8.GetString(buffer, 1, r - 1);
            //            int recive = r - 1;
            //            //Console.WriteLine(leng);
            //            //long recive = int.Parse(leng);
            //            //long recive = Convert.ToInt64(Encoding.UTF8.GetString(buffer, 1, r - 1));
            //            Console.WriteLine("总接受字节数:" + recive);
            //            long length = recive;
            //            Console.WriteLine("*******************************************");
            //            if (length > 0)
            //            {
            //                using (FileStream fsWrite = new FileStream(fullPath, FileMode.Append, FileAccess.Write))
            //                {
            //                    Console.WriteLine("---------*************--------------");
            //                    fsWrite.Write(buffer,1, r-1);
            //                    length -= r; //减去每次保存的字节数
            //                    Console.WriteLine("剩余接受字节数:"+length);
            //                    Console.WriteLine(string.Format("{0}: 已接收:{1}/{2}", socketClient.RemoteEndPoint, recive - length, recive));
            //                    if (length <= 0)
            //                    {
            //                        Console.WriteLine(socketClient.RemoteEndPoint + ": 接收文件成功");
            //                    }
            //                }
            //            }
            //        }


            //        //long recive = 0; //接收的大文件总的字节数
            //        //while (true)
            //        //{
            //        //    //byte[] buffer = new byte[1024 * 1024];
            //        //    //int r = socketClient.Receive(buffer);

            //        //    if (num == 0)
            //        //    {
            //        //        break;
            //        //    }
            //        //    if (length > 0)  //判断大文件是否已经保存完
            //        //    {
            //        //        //保存接收的文件
            //        //        using (FileStream fsWrite = new FileStream(fullPath, FileMode.Append, FileAccess.Write))
            //        //        {
            //        //            fsWrite.Write(result, 1, num-1);
            //        //            length -= num; //减去每次保存的字节数
            //        //            Console.WriteLine(string.Format("{0}: 已接收:{1}/{2}", socketClient.RemoteEndPoint, recive-length, recive));
            //        //            if (length <= 0)
            //        //            {
            //        //               Console.WriteLine(socketClient.RemoteEndPoint + ": 接收文件成功");
            //        //            }
            //        //            continue;
            //        //        }                        
            //        //    }
            //    }
            //}
            //catch (Exception ex)
            //{

            //    Console.WriteLine(ex.Message);
            //}

            //}

        }
    }
}
原文地址:https://www.cnblogs.com/macT/p/11661735.html