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);
        }
       

 

posted on 2017-05-31 11:54  听哥哥的话  阅读(1615)  评论(1编辑  收藏  举报

导航