zoukankan      html  css  js  c++  java
  • c#异步文件传输功能

    服务器端:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.Runtime.InteropServices;
    using System.IO;
    namespace RecvFileServer
    {
        /// <summary>
        /// 本文件主要处理多文件传输,首先做单文件传输,然后做多文件进行传输,今天完成对多文件发送.今天一定要写完成对多文件传输.能够进行测试成功
        /// </summary>
    
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        struct SendFileMessage
        {
            
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public char[] fileName;
            /// <summary>
            /// 传递的包类型。1 代表发送要创建的文件,2. 代表为第一条数据,但不是最后一条数据 3. 为中间传输数据,并非为最后一个,4. 代表文件最后一条数据 5. 第一条也是最后一条文件数据
            /// 1. 首先能够实现基本的单文件传输,单文件传输以后,便可以实现基本的多文件传输。
            /// </summary>
            public char typeMessage;
            //有效数据长度
            public int effDataLength;
            //有效数据
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
            public byte[] effData;
        }
    
        public class StateObject
        {
            // Client  socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 1037;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            //在此处,每个socket有对应额的一个FileStream
        }
    
        public class AsynchronousSocketServer
        {
            public static   FileStream writefile;
            public static ManualResetEvent allDone = new ManualResetEvent(false);
            private static Socket serverSocket;
            public static void StartAsynchronousSocket()
            {
                Console.WriteLine("服务器启动成功");
                IPAddress ipAddress = IPAddress.Parse("192.168.0.40");
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8083);
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    serverSocket.Bind(ipEndPoint);
                    serverSocket.Listen(1000);
                    while (true)
                    {
                        allDone.Reset();
                        serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), serverSocket);
                        allDone.WaitOne();
                    }
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    
            public static void AcceptCallback(IAsyncResult ar)
            {
                //在此处输出连接到的ip地址。当连接成功的时候,进行接收数据。handle指代的是连接到的client的socket
                Socket listener = (Socket)ar.AsyncState;
                Socket handler = listener.EndAccept(ar);
                allDone.Set();
                StateObject states = new StateObject();
                states.workSocket = handler;
                handler.BeginReceive(states.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(RecvCallback), states);
            }
    
            public static void RecvCallback(IAsyncResult ar)
            {
                //在此处进行设置一下,将其中的放入进去
                String content = String.Empty;
                //获取StateObject实例,并获取StateObject中的socket
                StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;
                //从client socket接收数据
                int bytesRead = handler.EndReceive(ar);
                if (bytesRead > 0)
                {
                    //判断读写的数据是否完成。如果没有,继续读写,如何判断是否接受完成呢?不能够使用EOF呢
                    if (bytesRead == 1037)
                    {
                        //获取传输到的数据,并转为Unicode字符,以便支持中文.在此处进行开始获取得到的数据,然后将获取到的数据转变为结构体类型
                        SendFileMessage sfm = new SendFileMessage();
                        sfm = (SendFileMessage)ByteToStruct(state.buffer, typeof(SendFileMessage));
                        Console.WriteLine(sfm.typeMessage);
                        //此处暂时把1去掉,改用在读取第一次的时候进行创建
                        if (sfm.typeMessage == '1')
                        {
    
                        }
                       else  if (sfm.typeMessage == '2') //2 代表的是文件对应的第一次,需要打开对应的文件,是否需要在SocketState中进行呢?
                        {
                            //每个客户端的连接可以的,依次放入其中呢。对每个客户进行的连接,我们都需要设置并将其中的连接放入到里面。现在都先放入debug文件目录下
    
                            String strPath = new String(sfm.fileName);
                            writefile = new FileStream(strPath + ".jpg", FileMode.OpenOrCreate);
                            writefile.Write(sfm.effData, 0, sfm.effDataLength);
    
                        }
                        else if (sfm.typeMessage == '3')
                        {
                            //如何根据其中的设置来进行。重新写发送部分,先能够成功接收一张<1K,=1K,>1K的文件;
                            writefile.Write(sfm.effData, 0, sfm.effDataLength);
                        }
                        else if (sfm.typeMessage == '4')
                        {
                           //代表最后一段数据,接受后写入到文件中,然后将文件关闭.每次打开后关闭,打开后关闭.在此处判断并将设置出来
                            writefile.Write(sfm.effData, 0, sfm.effDataLength);
                            writefile.Close();
                        }
                        else if (sfm.typeMessage =='5')
                        {
                            //如果此处为5代表文件大小小于1024字节,可以打开文件并进行存储.打开文件,把获取到的数据保存到新建的文件夹中.在此处接收成功。
                            //单文件进行传输,并将文件放入到里面
                            string strPath = new String(sfm.fileName);
                            writefile = new FileStream(strPath + ".jpg", FileMode.OpenOrCreate);
                            writefile.Write(sfm.effData, 0, sfm.effDataLength);
                            writefile.Close();
                        }
                    }
                }
                //使用异步接收,继续接收数据,将接收到的数据写入到文件中去,并将数据放入文件中去。成功接收两张图片。一个是<1024,一个是>1024并且余数!=0
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(RecvCallback), state);
            }
            public static byte[] StructToBytes(object structObj, int size)
            {
                int len = Marshal.SizeOf(structObj);
                byte[] bytes = new byte[size];
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                //将结构体拷到分配好的内存空间。
                Marshal.StructureToPtr(structObj, structPtr, false);
                //从内存空间拷贝到byte 数组欧拉模型外的另一种相机模型UVN系统。编写
                Marshal.Copy(structPtr, bytes, 0, size);
                //释放内存空间,为每个部分做大量的要求,并把其中的要求放入进去,背面消除方式。FreeHGlobal.
                Marshal.FreeHGlobal(structPtr);
                return bytes;
            }
    
            public static object ByteToStruct(byte[] bytes, Type type)
            {
                int size = Marshal.SizeOf(type);
                if (size > bytes.Length)
                {
                    return null;
                }
                //分配结构体空间,并把结构体AllocHGlobal(size);
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                //将byte数组拷贝到分配好的内存空间
                Marshal.Copy(bytes, 0, structPtr, size);
                //将内存空间转换为目标结构体
                object obj = Marshal.PtrToStructure(structPtr, type);
                //释放内存空间。
                Marshal.FreeHGlobal(structPtr);
                return obj;
            }
        }
    }
    

      客户端:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.IO;
    using System.Runtime.InteropServices;
    namespace SendFileClient
    {
    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    struct SendFileMessage
    {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public char[] fileName;
    //传递的包类型。1 代表发送要创建的文件,2. 代表为第一条数据 3. 为中间传输数据,并非为最后一个,4. 代表文件最后一条数据 5.第一条也是最后一条文件数据
    public char typeMessage;
    //有效数据长度
    public int effDataLength;
    //有效数据
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
    public byte[] effData;
    }

    class AsynchronousSocketClient
    {
    public static ManualResetEvent allDone = new ManualResetEvent(false);
    public static Socket client;
    public static void StartAsynchronousSocket()
    {
    IPAddress ipAddress = IPAddress.Parse("192.168.0.40");
    IPEndPoint ipPoint = new IPEndPoint(ipAddress, 8083);
    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    client.BeginConnect(ipPoint, new AsyncCallback(ConnectCallBack), client);
    allDone.WaitOne();
    while (true)
    {
    allDone.Reset();
    SendFile(client, "zhl.jpg", "20101112");
    SendFile(client, "jnvc.jpg", "20101113");
    allDone.WaitOne();
    }
    }

    public static void ConnectCallBack(IAsyncResult args)
    {
    Socket client = (Socket)args.AsyncState;
    client.EndConnect(args);
    Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
    allDone.Set();
    }

    public static void Send(Socket handler, String data)
    {
    // Convert the string data to byte data using ASCII encoding.
    byte[] byteData = Encoding.Unicode.GetBytes(data);
    // Begin sending the data to the remote device.此处发生错误?是否是因为其进行呢??
    handler.BeginSend(byteData, 0, byteData.Length, 0,
    new AsyncCallback(SendCallback), handler);
    }

    public static void Send(Socket handler, byte[] byteData)
    {
    handler.BeginSend(byteData, 0, byteData.Length, 0,
    new AsyncCallback(SendCallback), handler);
    }

    private static void SendCallback(IAsyncResult ar)
    {
    try
    {
    Socket handler = (Socket)ar.AsyncState;
    int bytesSent = handler.EndSend(ar);
    Console.WriteLine("Sent {0} bytes to server.", bytesSent);
    }
    catch (Exception e)
    {
    Console.WriteLine(e.ToString());
    }
    }


    public static void SendFile(Socket client, String filePath,String serverFileName)
    {

    byte[] sendByteMessage = new byte[1037];
    FileInfo fileInfo = new FileInfo(filePath);
    int fileSize = (int)(fileInfo.Length);
    FileStream afile = new FileStream(filePath, FileMode.Open);
    SendFileMessage sfm = new SendFileMessage();
    byte[] sendDataByte = new byte[1037];
    byte[] dataByte = new byte[1024];
    int i = (int)fileSize / 1024;
    int yu = (int)fileSize % 1024;

    //< = 1024 byte,则一次性把文件发送到服务器端
    //>1024 byte的 时候,余数为0和不为0的情况,如果余数为0
    if (fileSize <= 1024)
    {
    //在此处写入到2.jpg
    afile.Seek(0, SeekOrigin.Begin);
    afile.Read(dataByte, 0, fileSize);
    sfm.effData = dataByte;
    sfm.effDataLength = fileSize;

    sfm.fileName = (serverFileName.ToCharArray());
    sfm.typeMessage = '5';
    sendDataByte = StructToBytes(sfm, 1037);
    Send(client, sendDataByte);
    afile.Close();
    }
    else
    {
    if (yu != 0)
    {
    //余数不为0,则把其中的数据放入其中
    for (int j = 0; j < i; j++)
    {
    //重新为sendByteMessage赋值。文件数据大小必须要符合要求。不然会报错。使用光照引擎来进行

    sfm.fileName = serverFileName.ToCharArray();
    if (j == 0)
    {
    sfm.typeMessage = '2';
    sfm.fileName = serverFileName.ToCharArray();
    sfm.effDataLength = 1024;
    }
    else
    sfm.typeMessage = '3';
    afile.Seek(j * 1024, SeekOrigin.Begin);
    afile.Read(dataByte, 0, 1024);
    sfm.effData = dataByte;
    sendByteMessage = StructToBytes(sfm,1037);
    Send(client, sendByteMessage);
    //全部数据发送。一定是要再接收数据.判断其中的数据,放入到里面中
    }
    int seekNum = i * 1024;
    long operNum = (long)seekNum;
    afile.Seek(operNum, SeekOrigin.Begin);
    afile.Read(dataByte, 0, yu);
    //在此处重新组合sfm,然后发送次文件到sfm
    sfm.typeMessage='4';
    //在此处要把sfm转变为struct类型
    sendByteMessage = StructToBytes(sfm, 1037);
    Send(client, sendByteMessage);
    afile.Close();
    }
    else
    {
    for (int j = 0; j < i; j++)
    {
    afile.Seek(j * 1024, SeekOrigin.Begin);
    afile.Read(dataByte, 0, 1024);
    }
    afile.Close();
    }
    }
    }
    private static void AsynchronousFileSendCallback(IAsyncResult ar)
    {
    Socket client = (Socket)ar.AsyncState;
    client.EndSendFile(ar);
    }

    //当时怎么做的呢?的确是呢,可以呢?
    public static byte[] StructToBytes(object structObj, int size)
    {
    int len = Marshal.SizeOf(structObj);
    byte[] bytes = new byte[size];
    IntPtr structPtr = Marshal.AllocHGlobal(size);
    //将结构体拷到分配好的内存空间
    Marshal.StructureToPtr(structObj, structPtr, false);
    //从内存空间拷贝到byte数组
    Marshal.Copy(structPtr, bytes, 0, size);
    //释放内存空间,基于8bit
    Marshal.FreeHGlobal(structPtr);
    return bytes;
    }

    public static object ByteToStruct(byte[] bytes, Type type)
    {
    int size = Marshal.SizeOf(type);
    if (size > bytes.Length)
    {
    return null;
    }
    //分配结构体
    IntPtr structPtr = Marshal.AllocHGlobal(size);
    //将byte数组拷贝到分配好的内存空间
    Marshal.Copy(bytes, 0, structPtr, size);
    //将内存空间转换为目标结构体
    object obj = Marshal.PtrToStructure(structPtr,type);
    //释放内存空间 定向光源和点光源
    Marshal.FreeHGlobal(structPtr);
    return obj;
    }
    }
    }

  • 相关阅读:
    C指针
    redis五种基本数据类型
    mongoDB MapReduce
    JSON传参
    mongodb查询实练
    逻辑数据结构和存储数据结构
    线性表的顺序存储和链式存储
    数据结构和算法关系
    UIActivityIndicatorView使用
    Swift中格式化日期
  • 原文地址:https://www.cnblogs.com/sdnyzhl/p/3088207.html
Copyright © 2011-2022 走看看