Socket发送与接收文件
clent代码
private void button1_Click(object sender, EventArgs e) { IPEndPoint TestIP = new IPEndPoint(IPAddress.Parse("192.168.2.121"), 6666); FileTransmiter.Send(TestIP, "c:\\2.rar"); }
server代码
private void button1_Click(object sender, EventArgs e) { FileTransmiter.Listen("192.168.2.121", 6666); Thread.Sleep(5000); }
FileTransmiter类库
using System; using System.Net; using System.Net.Sockets; using System.IO; using System.Text; using System.Threading; using System.Collections.Generic; using System.Diagnostics; namespace Rocky { public static class FileTransmiter { /// <summary> /// 全局异常记录 /// </summary> #region Constructor static FileTransmiter() { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { StreamWriter writer = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "exec.log"), true, Encoding.Default); writer.Write("Time:"); writer.Write(DateTime.Now.ToShortTimeString()); writer.Write(". "); writer.WriteLine(e.ExceptionObject); writer.Dispose(); } #endregion /// <summary> /// 发送文件 /// </summary> /// <param name="ip"></param> /// <param name="path"></param> #region Single public static void Send(IPEndPoint ip, string path) { Stopwatch watcher = new Stopwatch();//计算时间 watcher.Start();//启用记时 Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//声明套接 sock.Connect(ip);//建立连接 byte[] buffer = new byte[BufferSize];//定义块 using (FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None))//读文件自动释放 { long send, length = reader.Length;//length读文件流的长度 Buffer.BlockCopy(BitConverter.GetBytes(length), 0, buffer, 0, PerLongCount);//把文件的8字节长度的内存复制到buffer里 string fileName = Path.GetFileName(path);//文件的扩展名 sock.Send(buffer, 0, PerLongCount + Encoding.Default.GetBytes(fileName, 0, fileName.Length, buffer, PerLongCount), SocketFlags.None); // Console.WriteLine("发送文件:" + fileName + ".请等待..."+ip.ToString()); sock.Receive(buffer);//接收从客服端发回的文件流长度存入缓冲区 reader.Position = send = BitConverter.ToInt64(buffer, 0);//文件流当前位置,设置文件流的位置 int read, sent;//read表示要发送的块的字节数, bool flag; while ((read = reader.Read(buffer, 0, BufferSize)) != 0)//读入buffer一个块的数据,返回字节数,则跳出.这里是循环发包 { sent = 0; flag = true; while ((sent += sock.Send(buffer, sent, read, SocketFlags.None)) < read)//循环发送buffer 从sent开始发送出read字节(read为块的字节量) { flag = false; send += (long)sent; } if (flag) //最后一个包运行 { send += (long)read; } } } sock.Shutdown(SocketShutdown.Both); sock.Close(); watcher.Stop(); // Console.WriteLine("Send finish.Span Time:" + watcher.Elapsed.TotalMilliseconds + " ms."); } // 监听端口 // 监听最大连接数 private static int listenCount = 2; //负责监听客户端连接请求的线程 private static Thread threadWatch = null; //用来保存客户端连接套接字 public static IPEndPoint SocketListenIP;//静态 //private Dictionary<string, Socket> dict = new Dictionary<string, Socket>(); //负责监听的套接字 private static Socket socketWatch = null; /// <summary> /// 开启监听 /// </summary> public static void Listen(string ip, int port) { SocketListenIP = new IPEndPoint(IPAddress.Parse(ip), port); //创建一个基于IPV4的TCP协议的Socket对象 if (socketWatch == null) { socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); } else { return; } //IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, listenPort); //创建一个网络端点 socketWatch.Bind(SocketListenIP);//将负责监听的套接字绑定到唯一的IP和端口 socketWatch.Listen(listenCount);//设置监听队列的长度 threadWatch = new Thread(WatchConnection); threadWatch.IsBackground = true;//设置为后台 threadWatch.Start();// 启动线程 } //监听客户端连接 private static void WatchConnection() { while (true) { if (socketWatch != null) { Socket sockConnection = socketWatch.Accept();//创建监听的连接套接字 //dict.Add(sockConnection.RemoteEndPoint.ToString(), sockConnection);//创建连接成功添加到dict对象里面 Thread t = new Thread(Receive); //为客户端套接字连接开启新的线程用于接收客户端发送的数据 t.IsBackground = true;//设置为后台线程 t.Start(sockConnection);//为客户端连接开启线程 } } } public const int BufferSize = 16;//1k*1024=1m 设定常数 public const int PerLongCount = sizeof(long);//常量表示8 public const int MinThreadCount = 1; public static void Receive(object obj) { //Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //listener.Bind(ip); //listener.Listen(MinThreadCount); //Socket client = listener.Accept();//以上步骤已在上面实现 Socket client = obj as Socket; //把这对象转换成Socket // Console.WriteLine(DateTime.Now.ToString("yyyyMMddhhmmssfffff"));//输出当前时间 //Console.WriteLine(Thread.CurrentThread.ManagedThreadId);//输出正在运行的进程 Stopwatch watcher = new Stopwatch();//测试运行时间 watcher.Start();//开始测试运行时间 byte[] buffer = new byte[BufferSize]; int received = client.Receive(buffer);//把接收的数据存入缓存区(所有接收的) long receive, length = BitConverter.ToInt64(buffer, 0);//转换为int64位8个字节来存储 string fileName = Encoding.Default.GetString(buffer, PerLongCount, received - PerLongCount); //转换回字符ANSI码的字符串,名称,在buffer,的PerLongCount位,received - PerLongCount字节大小 // fileName = DateTime.Now.ToString("yyyyMMddhhmmssfffff") + ".wav";//文件名为时间.wav // Console.WriteLine("Receiveing file:" + fileName + ".Plz wait...");//输出名称 FileInfo file = new FileInfo(Path.Combine("E:\\temp", fileName)); //保存到至文件名 using (FileStream writer = file.Open(file.Exists ? FileMode.Create : FileMode.CreateNew, FileAccess.Write, FileShare.None))//创建或覆盖 { receive = writer.Length;//字节的的流长度 client.Send(BitConverter.GetBytes(receive));//发送流长度 while (receive < length)//直到文件的流长度等于收到的流长度一样为止(因为长度与接收的文件不一至,所以正常来说套接是一直有数据的! { if ((received = client.Receive(buffer)) == 0) //如果接收到的信息为0(如果没数据就退出整个过程 { // Console.WriteLine("Send Stop.");//输出字符串 return; //跳出 } writer.Write(buffer, 0, received);//把buffer写入文件流块,从0开始,最多写入的字节数received writer.Flush();//清除缓存,并写入文件系统中 receive += (long)received;//文件流长度自增 } } client.Shutdown(SocketShutdown.Both);//停止接收 client.Close();//关闭资源 watcher.Stop();//停止测试计时 // Console.WriteLine("Receive finish.Span Time:" + watcher.Elapsed.TotalMilliseconds + " ms.");//输出运行所用时间 } #endregion } }