zoukankan      html  css  js  c++  java
  • 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:bbHQ.dat";
                string frompath = $@"d:aaHQ.dat";
                Net.FileMove("127.0.0.1", 11000, frompath, topath);
            }
           
  • 相关阅读:
    servlet中调用注入spring管理的dao(转)
    java枚举类(转)
    压缩包太大导致的部署问题
    oracle数据泵导出导入
    全错位排列
    母函数及相关的算法题
    Effective Modern C++翻译(5)-条款4:了解如何观察推导出的类型
    Effective Modern C++翻译(4)-条款3:了解decltype
    Effective Modern C++翻译(3)-条款2:明白auto类型推导
    Effective Modern C++翻译(2)-条款1:明白模板类型推导
  • 原文地址:https://www.cnblogs.com/kexb/p/6923437.html
Copyright © 2011-2022 走看看