首页 > 代码库 > 基于TCP网络通信的自动升级程序源码分析-客户端接收文件

基于TCP网络通信的自动升级程序源码分析-客户端接收文件

升级程序客户端接收文件

  /// <summary>        /// 文件数据缓存   索引是 ConnectionInfo对象  数据包的顺序号  值是数据        /// </summary>        Dictionary<ConnectionInfo, Dictionary<long, byte[]>> incomingDataCache = new Dictionary<ConnectionInfo, Dictionary<long, byte[]>>();        /// <summary>        /// 文件信息数据缓存     索引是 ConnectionInfo对象  数据包的顺序号  值是文件信息数据        /// </summary>        Dictionary<ConnectionInfo, Dictionary<long, SendInfo>> incomingDataInfoCache = new Dictionary<ConnectionInfo, Dictionary<long, SendInfo>>();

构造函数中注册

PartialFileData 逻辑类型 代表文件数据部分
PartialFileDataInfo 逻辑类型  代表文件数据相关信息部分
  //处理文件数据 <2  >            NetworkComms.AppendGlobalIncomingPacketHandler<byte[]>("PartialFileData", IncomingPartialFileData);            //处理文件信息 <3>            NetworkComms.AppendGlobalIncomingPacketHandler<SendInfo>("PartialFileDataInfo", IncomingPartialFileDataInfo);

具体的处理方法

        /// <summary>      /// 处理文件数据         /// </summary>              private void IncomingPartialFileData(PacketHeader header, Connection connection, byte[] data)        {            try            {                SendInfo info = null;                ReceiveFile file = null;                            lock (syncRoot)                {                                        //获取数据包的顺序号                    long sequenceNumber = header.GetOption(PacketHeaderLongItems.PacketSequenceNumber);                    //如果数据信息字典包含 "连接信息" 和  "包顺序号"                    if (incomingDataInfoCache.ContainsKey(connection.ConnectionInfo) && incomingDataInfoCache[connection.ConnectionInfo].ContainsKey(sequenceNumber))                    {                                                 //根据顺序号,获取相关SendInfo记录                        info = incomingDataInfoCache[connection.ConnectionInfo][sequenceNumber];                        //从信息记录字典中删除相关记录                        incomingDataInfoCache[connection.ConnectionInfo].Remove(sequenceNumber);                                                //检查相关连接上的文件是否存在,如果不存在,则添加相关文件{ReceiveFile}                        if (!recvManager.ContainsFileID(info.FileID))                        {                             recvManager.AddFile(info.FileID, info.Filename, info.FilePath, connection.ConnectionInfo, info.TotalBytes);                         }                        file = recvManager.GetFile(info.FileID);                    }                    else                    {                                              //如果不包含顺序号,也不包含相关"连接信息",添加相关连接信息                        if (!incomingDataCache.ContainsKey(connection.ConnectionInfo))                            incomingDataCache.Add(connection.ConnectionInfo, new Dictionary<long, byte[]>());                        //在数据字典中添加相关"顺序号"的信息                        incomingDataCache[connection.ConnectionInfo].Add(sequenceNumber, data);                    }                }                                if (info != null && file != null && !file.IsCompleted)                {                    file.AddData(info.BytesStart, 0, data.Length, data);                                        file = null;                    data = null;                                   }                else if (info == null ^ file == null)                    throw new Exception("Either both are null or both are set. Info is " + (info == null ? "null." : "set.") + " File is " + (file == null ? "null." : "set.") + " File is " + (file.IsCompleted ? "completed." : "not completed."));            }            catch (Exception ex)            {                                LogTools.LogException(ex, "IncomingPartialFileDataError");            }        }                        /// 处理文件数据信息                       private void IncomingPartialFileDataInfo(PacketHeader header, Connection connection, SendInfo info)        {            try            {                byte[] data = http://www.mamicode.com/null;                ReceiveFile file = null;                //以线程安全的方式执行操作                lock (syncRoot)                {                                    //从 SendInfo类中获取相应数据类的信息号 以便可以对应。                    long sequenceNumber = info.PacketSequenceNumber;                    if (incomingDataCache.ContainsKey(connection.ConnectionInfo) && incomingDataCache[connection.ConnectionInfo].ContainsKey(sequenceNumber))                    {                                                data = incomingDataCache[connection.ConnectionInfo][sequenceNumber];                        incomingDataCache[connection.ConnectionInfo].Remove(sequenceNumber);                         if (!recvManager.ContainsFileID(info.FileID))                        {                                                        recvManager.AddFile(info.FileID, info.Filename, info.FilePath, connection.ConnectionInfo, info.TotalBytes);                         }                        file = recvManager.GetFile(info.FileID);                    }                    else                    {                                               if (!incomingDataInfoCache.ContainsKey(connection.ConnectionInfo))                            incomingDataInfoCache.Add(connection.ConnectionInfo, new Dictionary<long, SendInfo>());                        incomingDataInfoCache[connection.ConnectionInfo].Add(sequenceNumber, info);                    }                }                                if (data != null && file != null && !file.IsCompleted)                {                    file.AddData(info.BytesStart, 0, data.Length, data);                                    file = null;                    data = null;                                   }                else if (data =http://www.mamicode.com/= null ^ file == null)                    throw new Exception("Either both are null or both are set. Data is " + (data =http://www.mamicode.com/= null ? "null." : "set.") + " File is " + (file == null ? "null." : "set.") + " File is " + (file.IsCompleted ? "completed." : "not completed."));            }            catch (Exception ex)            {                                LogTools.LogException(ex, "IncomingPartialFileDataInfo");            }        }

ReceiveFile类

 public class ReceiveFile : INotifyPropertyChanged    {        //传输过程        public event EventHandler<FTProgressEventArgs> FileTransProgress;        //传输完成        public event EventHandler<FTCompleteEventArgs> FileTransCompleted;        //传输中断        public event EventHandler<FTDisruptEventArgs> FileTransDisruptted;         /// <summary>        /// The name of the file        /// 文件名  (没有带路径)        /// </summary>        public string Filename { get; private set; }        /// <summary>        /// The connectionInfo corresponding with the source        /// 连接信息        /// </summary>        public ConnectionInfo SourceInfo { get; private set; }        //文件ID  用于管理文件 和文件的发送 取消发送相关        private string fileID;        public string FileID        {            get { return fileID; }            set { fileID = value; }        }        /// <summary>        /// The total size in bytes of the file        /// 文件的字节大小        /// </summary>        public long SizeBytes { get; private set; }        /// <summary>        /// The total number of bytes received so far        /// 目前收到的文件的带下        /// </summary>        public long ReceivedBytes { get; private set; }        /// <summary>        /// Getter which returns the completion of this file, between 0 and 1        ///已经完成的百分比        /// </summary>        public double CompletedPercent        {            get { return (double)ReceivedBytes / SizeBytes; }             set { throw new Exception("An attempt to modify read-only value."); }        }        /// <summary> /// 源信息        /// </summary>        public string SourceInfoStr        {            get { return "[" + SourceInfo.RemoteEndPoint.ToString() + "]"; }        }        /// <summary> /// 是否完成        /// </summary>        public bool IsCompleted        {            get { return ReceivedBytes == SizeBytes; }        }           object SyncRoot = new object();        /// <summary> /// 用来创建文件的数据流        /// </summary>        Stream data;            public event PropertyChangedEventHandler PropertyChanged;        //临时文件流存储的位置        public string TempFilePath = "";        //文件最后的保存路径        public string SaveFilePath = "";              public ReceiveFile(string fileID, string filename, string filePath, ConnectionInfo sourceInfo, long sizeBytes)        {            this.fileID = fileID;            this.Filename = filename;            this.SourceInfo = sourceInfo;            this.SizeBytes = sizeBytes;            //如果临时文件已经存在,则添加.data后缀            this.TempFilePath = filePath + ".data";            while (File.Exists(this.TempFilePath))            {                this.TempFilePath = this.TempFilePath + ".data";            }            this.SaveFilePath = filePath;            //We create a file on disk so that we can receive large files            //我们在硬盘上创建一个文件,使得我们可以接收大的文件            //data = http://www.mamicode.com/new FileStream(TempFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 8 * 1024, FileOptions.DeleteOnClose);            data = http://www.mamicode.com/new FileStream(this.TempFilePath, FileMode.OpenOrCreate);         }         /// <summary>     /// 添加数据到文件中        /// </summary>              public void AddData(long dataStart, int bufferStart, int bufferLength, byte[] buffer)        {            lock (SyncRoot)            {                if (!this.canceled && (this.data != null))                {                    try                    {                        data.Seek(dataStart, SeekOrigin.Begin);                        data.Write(buffer, (int)bufferStart, (int)bufferLength);                        ReceivedBytes += (int)(bufferLength - bufferStart);                                                 FileTransProgress.Raise(this, new FTProgressEventArgs(FileID, SizeBytes, ReceivedBytes));                        if (ReceivedBytes == SizeBytes)                        {                            //data.Flush();                            //SaveFileToDisk(SaveFilePath);                            //data.Close();                            this.data.Flush();                            this.data.Close();                            if (File.Exists(this.SaveFilePath))                            {                                File.Delete(this.SaveFilePath);                                File.Move(this.TempFilePath, this.SaveFilePath);                            }                            else                            {                                File.Move(this.TempFilePath, this.SaveFilePath);                            }                             FileTransCompleted.Raise(this, new FTCompleteEventArgs(FileID));                        }                    }                    catch (Exception exception)                    {                        //触发文件传输中断事件                                               FileTransDisruptted.Raise(this, new FTDisruptEventArgs(FileID, FileTransFailReason.Error));                    }                }            }                  }        private volatile bool canceled;        public void Cancel(FileTransFailReason disrupttedType, bool deleteTempFile)        {            try            {                this.canceled = true;                this.data.Flush();                this.data.Close();                this.data = http://www.mamicode.com/null;                if (deleteTempFile)                {                    File.Delete(this.TempFilePath);                }            }            catch (Exception)            {            }            //通知 Receiver取消,并且触发文件传输中断事件            FileTransDisruptted.Raise(this, new FTDisruptEventArgs(FileID, FileTransFailReason.Error));        }                  public void Close()        {            try            {                data.Dispose();            }            catch (Exception) { }            try            {                data.Close();            }            catch (Exception) { }        }            }

ReceiveFileDict

 public  class ReceiveFileDict    {        private object syncLocker = new object();        Dictionary<string, ReceiveFile> receivedFiles = new Dictionary<string, ReceiveFile>();        public bool ContainsFileID(string fileID)        {            lock (syncLocker)            {                return receivedFiles.ContainsKey(fileID);            }        }        public ReceiveFile GetFile(string fileID)        {            lock (syncLocker)            {                return receivedFiles[fileID];            }        }        //传输过程        public event EventHandler<FTProgressEventArgs> FileTransProgress;        //传输完成        public event EventHandler<FTCompleteEventArgs> FileTransCompleted;        //传输中断        public event EventHandler<FTDisruptEventArgs> FileTransDisruptted;        public event EventHandler<FTCancelEventArgs> FileCancelRecv;        public ReceiveFileDict()        {        }        public void AddFile(string fileID, string filename, string filePath, ConnectionInfo sourceInfo, long sizeBytes)        {            ReceiveFile receivedFile = new ReceiveFile(fileID,filename,filePath,sourceInfo,sizeBytes);             receivedFile.FileTransProgress += new EventHandler<FTProgressEventArgs>(receivedFile_FileTransProgress);            receivedFile.FileTransCompleted += new EventHandler<FTCompleteEventArgs>(receivedFile_FileTransCompleted);            receivedFile.FileTransDisruptted += new EventHandler<FTDisruptEventArgs>(receivedFile_FileTransDisruptted);            receivedFiles.Add(fileID, receivedFile);        }        void receivedFile_FileTransDisruptted(object sender, FTDisruptEventArgs e)        {            lock (this.syncLocker)            {                if (this.receivedFiles.ContainsKey(e.FileID))                {                    this.receivedFiles.Remove(e.FileID);                }             }                         FileTransDisruptted.Raise(this, e);        }        void receivedFile_FileTransCompleted(object sender, FTCompleteEventArgs e)        {            lock (this.syncLocker)            {                if (this.receivedFiles.ContainsKey(e.FileID))                {                    this.receivedFiles.Remove(e.FileID);                }            }                       FileTransCompleted.Raise(this, e);        }        void receivedFile_FileTransProgress(object sender, FTProgressEventArgs e)        {            FileTransProgress.Raise(this, e);        }          //  请求取消文件的接收  FileRecTransViewer中会调用此方法        public void CancelRecFile(string fileID)        {             FileCancelRecv.Raise(this, new FTCancelEventArgs(fileID));        }    }

 www.networkcomms.cn

www.cnblogs.com/networkcomms

【开源下载】基于TCP网络通信的自动升级程序c#源码

[源码下载]Demo2.模拟简单登陆-效果图 基于networkcomms2.3.1

[源码下载]Demo1 客户端从服务器获取信息(基于networkcomms2.3.1)

 http://shop115882994.taobao.com/

相关文章:

基于TCP网络通信的自动升级程序源码分析--生成升级文件相关的配置文件

基于TCP网络通信的自动升级程序源码分析-客户端连接服务器

基于TCP网络通信的自动升级程序源码分析-客户端请求服务器上的升级信息

基于TCP网络通信的自动升级程序源码分析-启动升级文件下载程序

基于TCP网络通信的自动升级程序源码分析-服务器发送文件

基于TCP网络通信的自动升级程序源码分析-客户端接收文件

基于TCP网络通信的自动升级程序源码分析-客户端接收文件