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:\IVS\Down"; //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() + "\r\n" + GetTime() + "\r\n" + recMsg + "\r\n"); } 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:\Users\Administrator\Desktop"; // //sfd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; // //如果没有选择保存文件路径就一直打开保存框 // SaveFileDialog save = new SaveFileDialog();//创建SaveFileDialog实例 // string spath = @"C:\Users\admin\Desktop";//制定存储路径 // 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:\Users\admin\Desktop";//制定存储路径 // 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); //} //} } } }
赞 (0)