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


    }
}

 

posted @ 2016-05-21 16:48  天祈笨笨  阅读(303)  评论(0编辑  收藏  举报