示例#1
0
        /// <summary>
        /// 解析请求的命令
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="startIndex"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        Message ParseSendCommand(byte[] buffer, int startIndex, int length)
        {
            byte[] cmdInfo = new byte[length];
            Array.Copy(buffer, 0, cmdInfo, 0, length);

            if (!MessagePacker.Test(cmdInfo))
            {
                return(null);
            }
            Message msg = MessagePacker.TryToTranslateMessage(cmdInfo, null);

            if (msg == null || (msg.Command != Consts.Commands.GetDirFiles && msg.Command != Consts.Commands.GetFileData))
            {
                return(null);
            }

            return(msg);
        }
示例#2
0
        /// <summary>
        /// 尝试将收到的消息解析为实体对象
        /// </summary>
        /// <param name="buffer">封包消息</param>
        /// <param name="remoteEndPoint">远程主机的端点位置</param>
        /// <returns></returns>
        /// <remarks>如果是分包的消息且当前并未接收完全,则同样返回为空</remarks>
        public Message ResolveToMessage(byte[] buffer, IPEndPoint remoteEndPoint)
        {
            if (buffer == null || buffer.Length < 0)
            {
                return(null);
            }

            Message m = null;

            if (MessagePacker.Test(buffer))
            {
                m = MessagePacker.TryToTranslateMessage(buffer, remoteEndPoint);

                if (m != null)
                {
                    m.Host = LivedHost.GetHost(remoteEndPoint.Address.ToString());

                    //确认是否要发送回复
                    if (DetermineConfirm(m))
                    {
                        Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName,
                                                    FSLib.IPMessager.Define.Consts.Commands.RecvMsg, 0, m.PackageNo.ToString(), "");
                        Send(cm);
                    }
                }
            }
            else if (MessagePackerV2.Test(buffer))
            {
                PackedNetworkMessage pack = MessagePackerV2.Parse(buffer, remoteEndPoint);

                if (pack == null)
                {
                    return(null);
                }

                if (DetermineConfirm(pack))
                {
                    //发送确认标志
                    Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName,
                                                FSLib.IPMessager.Define.Consts.Commands.Ex_PackageRecevied, 0, pack.PackageNo.ToString(), pack.PackageIndex.ToString());
                    Send(cm);
                }
                m = MessagePackerV2.TryToTranslateMessage(pack);

                if (m != null)
                {
                    m.Host = LivedHost.GetHost(remoteEndPoint.Address.ToString());

                    //确认是否要发送回复
                    if (DetermineConfirm(m))
                    {
                        Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName,
                                                    FSLib.IPMessager.Define.Consts.Commands.RecvMsg, 0, m.PackageNo.ToString(), "");
                        Send(cm);
                    }
                    if (DetermineConfirm2(m))
                    {
                        Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName,
                                                    FSLib.IPMessager.Define.Consts.Commands.AnsReadMsg, 0, m.PackageNo.ToString(), "");
                        Send(cm);
                    }
                }
            }

            return(m);
        }
示例#3
0
        protected virtual void OnFileSystemOperationError(FileSystemOperationErrorEventArgs e)
        {
            if (FileSystemOperationError == null)
            {
                return;
            }

            if (!IPMClient.NeedPostMessage)
            {
                FileSystemOperationError(this, e);
            }
            else
            {
                if (scpcFileSystemOperationError == null)
                {
                    scpcFileSystemOperationError = (s) => { FileSystemOperationError(this, s as FileSystemOperationErrorEventArgs); }
                }
                ;
                IPMClient.SendASynchronizeMessage(scpcFileSystemOperationError, e);
            }
        }

        #region 发送文件事件



        #endregion


        #endregion

        #region 发送文件-监听线程

        /// <summary>
        /// 开始发送文件的监听线程
        /// </summary>
        void StartListener()
        {
            System.Threading.ThreadStart ts = ListenForSendRequest;
            new System.Threading.Thread(ts)
            {
                IsBackground = true
            }.Start();
        }

        /// <summary>
        /// 关闭监听线程
        /// </summary>
        void CloseListener()
        {
            listener.Stop();
            IsInitialized = false;
        }

        /// <summary>
        /// 监听函数
        /// </summary>
        void ListenForSendRequest()
        {
            listener.Start();
            while (IsInitialized)
            {
                try
                {
                    TcpClient client = listener.AcceptTcpClient();
                    //开始发送线程
                    if (client != null)
                    {
                        System.Diagnostics.Debug.WriteLine("文件发送线程:已经接收到连接请求,远程IP:" + client.Client.RemoteEndPoint.ToString());

                        new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(PerformFileSend))
                        {
                            IsBackground = true
                        }.Start(client);
                    }
                }
                catch (Exception)
                {
                    if (!IsInitialized)
                    {
                        break;
                    }
                }
            }
        }

        #endregion
        #region 发送文件-发送线程

        /// <summary>
        /// 处理文件发送请求
        /// </summary>
        /// <param name="client"></param>
        void PerformFileSend(object p)
        {
            System.Diagnostics.Debug.WriteLine("文件发送线程 [0x" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString("X4") + "] 已经启动");

            using (TcpClient client = p as TcpClient)
            {
                byte[] buffer        = new byte[400];                                  //接收或发送缓冲区
                int    bytesReceived = ReceiveByBuffer(client, buffer, buffer.Length); //第一步:接收文件传输命令

                if (bytesReceived < 1)
                {
                    return;                                                   //没收到数据
                }
                Message request = ParseSendCommand(buffer, 0, bytesReceived); //试着解析命令
                System.Diagnostics.Debug.WriteLineIf(request == null, "未能解析收到的请求,退出发送线程");

                if (request == null)
                {
                    return;
                }
                System.Diagnostics.Debug.WriteLine("已解析文件请求:" + request.NormalMsg.ToString());

                //非法请求
                //查找任务
                string[] taskInfo = request.NormalMsg.Split(':');
                ulong    pid      = 0ul;
                int      tid      = 0;

                FileTaskItem task = null;
                if (taskInfo.Length < 2 ||
                    !ulong.TryParse(taskInfo[0], System.Globalization.NumberStyles.AllowHexSpecifier, null, out pid) ||
                    !int.TryParse(taskInfo[1], System.Globalization.NumberStyles.AllowHexSpecifier, null, out tid) ||
                    (task = TaskManager.QuerySendTask(pid, tid, (client.Client.RemoteEndPoint as IPEndPoint).Address)) == null
                    )
                {
                    return;
                }
                System.Diagnostics.Debug.WriteLine(string.Format("文件请求已经接纳,文件编号:0x{0:x8},文件索引:0x{1:x4}", pid, tid));

                TaskManager.MarkSendTaskItemState(task, FileTaskItemState.Initializing);
                //准备发送
                if (task.IsFolder)
                {
                    PerformSendDirectory(client, task.TaskInfo, task);
                }
                else
                {
                    //文件支持有限的断点续传
                    if (taskInfo.Length == 3)
                    {
                        ulong temp;
                        if (ulong.TryParse(taskInfo[2], out temp))
                        {
                            task.CurrentFileTransfered = temp;
                            task.FileTransferedAtPast  = temp;
                        }
                        System.Diagnostics.Debug.WriteLineIf(task.CurrentFileTransfered > 0, string.Format("断点模式,从 0x{0} 处开始续传", task.CurrentFileTransfered));
                    }

                    PerformSendFile(client, task.TaskInfo, task);
                }
                client.Close();
            }
        }

        //发送文件夹
        void PerformSendDirectory(TcpClient client, FileTaskInfo task, FileTaskItem item)
        {
            NetworkStream stream = null;

            try
            {
                stream = client.GetStream();
            }
            catch (Exception)
            {
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                return;
            }

            string         currentDirectory = item.FullPath;                    //当前处理路径
            Stack <string> directoryStack   = new Stack <string>();             //文件夹栈

            directoryStack.Push("");

            bool needUpdateTotal = item.TotalSize == 0;                         //是否需要在发送的时候更新统计

            TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Processing);
            item.StartTime = DateTime.Now;

            using (stream)
            {
                while (!string.IsNullOrEmpty(currentDirectory) || directoryStack.Count > 0)
                {
                    if (!PerformSendDirectory_SendCreateDirCommand(currentDirectory, stream, task, item))
                    {
                        return;
                    }
                    if (string.IsNullOrEmpty(currentDirectory))
                    {
                        if (directoryStack.Count > 0)
                        {
                            currentDirectory = directoryStack.Pop();                                                    //当前是空目录,则向上递归
                        }
                        continue;
                    }

                    //扫描目录和文件
                    string[] files = null, directories = null;
                    try
                    {
                        files       = System.IO.Directory.GetFiles(currentDirectory);
                        directories = System.IO.Directory.GetDirectories(currentDirectory);

                        item.FolderCount += directories.Length;
                        item.FileCount   += files.Length;
                    }
                    catch (Exception)
                    {
                        TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                        OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.QueryDirectory, item.FullPath, task.RemoteHost));
                        return;
                    }

                    //优先发送文件
                    foreach (var f in files)
                    {
                        if (!PerformSendDirectory_SendFilesInDirectory(f, stream, task, item, needUpdateTotal))
                        {
                            return;
                        }
                    }

                    //扫描子目录
                    if (directories.Length > 0)
                    {
                        directoryStack.Push("");
                        Array.ForEach(directories, s => { directoryStack.Push(s); });
                        currentDirectory = directoryStack.Pop();                                //取出一个文件夹来发送
                    }
                    else
                    {
                        //如果没有子目录,则置空当前目录,以命令流程向上返回
                        currentDirectory = null;
                    }
                }
                if (item.State != FileTaskItemState.Failure)
                {
                    TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Finished);
                }
            }
        }

        //发送文件夹中的文件
        bool PerformSendDirectory_SendFilesInDirectory(string path, NetworkStream stream, FileTaskInfo task, FileTaskItem item, bool updateTotal)
        {
            System.IO.FileInfo fileinfo = new System.IO.FileInfo(path);
            if (!fileinfo.Exists)
            {
                OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.OpenFileToSend, path, task.RemoteHost));
            }

            if (updateTotal)
            {
                item.TotalSize += (ulong)fileinfo.Length;
            }
            item.CurrentName           = fileinfo.Name;
            item.CurrentFileTransfered = 0;
            item.CurrentFileSize       = (ulong)fileinfo.Length;

            string strCMD = string.Format(":{0}:{1:x}:{2:x}:", fileinfo.Name, fileinfo.Length, (int)Consts.Cmd_FileType_Option.Regular);

            byte[] bytes = null;
            if (task.RemoteHost.IsEnhancedContractEnabled)
            {
                bytes = System.Text.Encoding.Unicode.GetBytes(strCMD);
            }
            else
            {
                bytes = System.Text.Encoding.Default.GetBytes(strCMD);
            }

            try
            {
                stream.Write(System.Text.Encoding.Default.GetBytes((bytes.Length + 4).ToString("x4")), 0, 4);
                stream.Write(bytes, 0, bytes.Length);
            }
            catch (Exception)
            {
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                return(false);
            }

            //写入文件数据
            FileStream reader = null;

            try
            {
                reader = fileinfo.OpenRead();
            }
            catch (Exception)
            {
                OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.OpenFileToSend, path, task.RemoteHost));
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                return(false);
            }

            using (reader)
            {
                byte[] buffer = new byte[SendBuffer];
                while (item.CurrentFileTransfered < (ulong)reader.Length)
                {
                    int bytesRead = reader.Read(buffer, 0, buffer.Length);
                    item.CurrentFileTransfered += (ulong)bytesRead;
                    item.FinishedSize          += (ulong)bytesRead;

                    try
                    {
                        stream.Write(buffer, 0, bytesRead);
                    }
                    catch (Exception)
                    {
                        TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                        return(false);
                    }
                }
                reader.Close();
            }
            item.FinishedFileCount++;

            return(true);
        }

        //发送要求创建文件命令
        bool PerformSendDirectory_SendCreateDirCommand(string path, NetworkStream stream, FileTaskInfo task, FileTaskItem item)
        {
            string strCMD = string.Format(":{0}:{1}:{2:x}:", string.IsNullOrEmpty(path) ? "." : System.IO.Path.GetFileName(path), 0, (int)(string.IsNullOrEmpty(path) ? Consts.Cmd_FileType_Option.RetParent : Consts.Cmd_FileType_Option.Dir));

            byte[] bytes = null;
            if (task.RemoteHost.IsEnhancedContractEnabled)
            {
                bytes = System.Text.Encoding.Unicode.GetBytes(strCMD);
            }
            else
            {
                bytes = System.Text.Encoding.Default.GetBytes(strCMD);
            }

            if (!string.IsNullOrEmpty(path))
            {
                item.FinishedFolderCount++;
            }

            try
            {
                stream.Write(System.Text.Encoding.Default.GetBytes((bytes.Length + 4).ToString("x4")), 0, 4);
                stream.Write(bytes, 0, bytes.Length);
                return(true);
            }
            catch (Exception)
            {
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                return(false);
            }
        }

        /// <summary>
        /// 发送单个文件
        /// </summary>
        /// <param name="client"></param>
        /// <param name="task"></param>
        /// <param name="item"></param>
        void PerformSendFile(TcpClient client, FileTaskInfo task, FileTaskItem item)
        {
            System.IO.FileStream             fs     = null;
            System.Net.Sockets.NetworkStream writer = null;
            try
            {
                writer = client.GetStream();
            }
            catch (Exception)
            {
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                return;
            }
            try
            {
                fs = new System.IO.FileStream(item.FullPath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            }
            catch (Exception)
            {
                if (writer != null)
                {
                    writer.Close();
                }
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.OpenFileToSend, item.FullPath, task.RemoteHost));

                return;
            }
            using (fs)
            {
                //检测断点数据是否正确
                if (item.CurrentFileTransfered < 0 || item.CurrentFileTransfered > (ulong)fs.Length)
                {
                    item.CurrentFileTransfered = 0;
                }
                fs.Seek((long)item.CurrentFileTransfered, System.IO.SeekOrigin.Begin);

                //设置当前任务信息
                item.CurrentFileSize = (ulong)fs.Length;
                TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Processing);
                item.StartTime = DateTime.Now;

                using (writer)
                {
                    byte[] buffer = new byte[SendBuffer];                       //缓冲区

                    while (item.CurrentFileTransfered < item.CurrentFileSize)
                    {
                        int bytesRead = fs.Read(buffer, 0, buffer.Length);
                        try
                        {
                            writer.Write(buffer, 0, bytesRead);
                        }
                        catch (Exception)
                        {
                            TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure);
                            break;
                        }

                        //更新进度
                        item.CurrentFileTransfered += (ulong)bytesRead;
                        item.FinishedSize          += (ulong)bytesRead;
                    }
                    item.FinishedFileCount++;
                    writer.Close();
                }
                fs.Close();
                //标记任务完成
                if (item.State != FileTaskItemState.Failure)
                {
                    TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Finished);
                }
            }
        }

        /// <summary>
        /// 解析请求的命令
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="startIndex"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        Message ParseSendCommand(byte[] buffer, int startIndex, int length)
        {
            byte[] cmdInfo = new byte[length];
            Array.Copy(buffer, 0, cmdInfo, 0, length);

            if (!MessagePacker.Test(cmdInfo))
            {
                return(null);
            }
            Message msg = MessagePacker.TryToTranslateMessage(cmdInfo, null);

            if (msg == null || (msg.Command != Consts.Commands.GetDirFiles && msg.Command != Consts.Commands.GetFileData))
            {
                return(null);
            }

            return(msg);
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="buffer">缓冲区</param>
        /// <returns></returns>
        int ReceiveByBuffer(TcpClient client, byte[] buffer)
        {
            try
            {
                return(client.Client.Receive(buffer));
            }
            catch (Exception)
            {
                //网络异常
                return(-1);
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="buffer">缓冲区</param>
        /// <returns></returns>
        int ReceiveByBuffer(TcpClient client, byte[] buffer, int length)
        {
            try
            {
                return(client.Client.Receive(buffer, length, SocketFlags.None));
            }
            catch (Exception)
            {
                //网络异常
                return(-1);
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="buffer">缓冲区</param>
        /// <returns></returns>
        int ReceiveByBuffer(NetworkStream stream, byte[] buffer)
        {
            try
            {
                return(stream.Read(buffer, 0, buffer.Length));
            }
            catch (Exception)
            {
                //网络异常
                return(-1);
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="buffer">缓冲区</param>
        /// <returns></returns>
        int ReceiveByBuffer(NetworkStream stream, byte[] buffer, int length)
        {
            try
            {
                return(stream.Read(buffer, 0, length));
            }
            catch (Exception)
            {
                //网络异常
                return(-1);
            }
        }

        #endregion

        #region 接收文件

        /// <summary>
        /// 请求接收文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _taskManager_FileReceiveRequired(object sender, FileReceiveRequiredEventArgs e)
        {
            if (!IsInitialized)
            {
                return;
            }

            new Thread(() => { PerformFileReceive(e.Task, e.Item); })
            {
                IsBackground = true
            }.Start();
        }