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

服务器发送文件

复制代码
using System;
using System.Collections.Generic;
 
using System.Text;

using NetworkCommsDotNet;
using System.ComponentModel;
using System.IO;
 
using NetworkCommsDotNet.Connections;
using NetworkCommsDotNet.Tools;
using NetworkCommsDotNet.Connections.TCP;
using System.Threading;
using Upgrade.Business;
using NetworkCommsDotNet.DPSBase;

namespace AppServer
{
   
    public class SendFile 
    {
         
        //传输过程
        public event EventHandler<FTProgressEventArgs> FileTransProgress;
        //传输完成
        public event EventHandler<FTCompleteEventArgs> FileTransCompleted;
        //传输中断
        public event EventHandler<FTDisruptEventArgs> FileTransDisruptted;
        //取消文件的发送
        private volatile bool canceled = false;
        //文件传送失败的原因
        private FileTransFailReason fileTransDisrupttedType = FileTransFailReason.Error;
        
        public string FilePath { get; private set; }

        /// <summary>
        /// The connectionInfo corresponding with the source
        /// 连接信息
        /// </summary>
        public ConnectionInfo SourceInfo { get; private set; }

        /// <summary>
        /// 收发参数
        /// </summary>
        private SendReceiveOptions sendFileOptions = null;
        


        private Connection connection;

        public Connection Connection
        {
            get { return connection;}
            set { connection = value;}
        }

        //文件发送相关参数
        private FileTransOptions fileTransOptions;

        public FileTransOptions FileTransOptions
        {
            get { return fileTransOptions; }
            set { fileTransOptions = value; }
        }

        //文件ID  用于管理文件 和文件的发送 取消发送相关

        private string fileID;

        public string FileID
        {
            get { return fileID; }
            set { fileID = value; }
        }
        //文件传输后存储的路径  客户端传过来的路径  再传回去 
        private string destFilePath;

        public string DestFilepath
        {
            get { return destFilePath; }
            set { destFilePath = 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 SentBytes { get; private set; }

        /// <summary>
        /// Getter which returns the completion of this file, between 0 and 1
        ///已经完成的百分比
        /// </summary>
        public double CompletedPercent
        {
            get { return (double)SentBytes / SizeBytes; }

            //This set is required for the application to work
            set { throw new Exception("An attempt to modify read-only value."); }
        }

        /// <summary>
        /// A formatted string of the SourceInfo
        /// 源信息
        /// </summary>
        public string SourceInfoStr
        {
            get { return "[" + SourceInfo.RemoteEndPoint.ToString() + "]"; }
        }

        /// <summary>
        /// Returns true if the completed percent equals 1
        /// 是否完成
        /// </summary>
        public bool IsCompleted
        {
            get { return SentBytes == SizeBytes; }
        }

        /// <summary>
        /// Private object used to ensure thread safety
        /// </summary>
        object SyncRoot = new object();

      
       //构造函数
        
        public SendFile(string fileID, string filePath, string destFilePath, Connection connection, SendReceiveOptions sendReceiveOptions, FileTransOptions fileTransOptions)
        {
            //文件ID
            this.fileID = fileID;
            this.FilePath = filePath;
            this.destFilePath = destFilePath;
        
            this.connection = connection;
            
            this.fileTransOptions = fileTransOptions;

            this.sendFileOptions = new SendReceiveOptions(DPSManager.GetDataSerializer<ProtobufSerializer>(), null, null);
            this.sendFileOptions.ReceiveHandlePriority = NetworkCommsDotNet.Tools.QueueItemPriority.Lowest;

                     
        }
         //异步方法发送文件
        public void NowSendFile()
        {
            new Action(this.StartSendFile).BeginInvoke(null, null);
        }

        //发送文件
        public  void StartSendFile()
        {
            FileStream stream = null;
            try
            {
                //Create a fileStream from the selected file
                //根据选择的文件创建一个文件流
                stream = new FileStream(this.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                 
               //包装成线程安全的数据流
                StreamTools.ThreadSafeStream safeStream = new StreamTools.ThreadSafeStream(stream);

                //Get the filename without the associated path information
                //获取不包含路径信息的文件名
                string shortFileName = System.IO.Path.GetFileName(FilePath);
                  
                //根据参数中设定的值来角色发送的数据包的大小
                long sendChunkSizeBytes = fileTransOptions.PackageSize;


                this.SizeBytes = stream.Length;

                long totalBytesSent = 0;

                do
                {
                    // 此次发送的字节数
                    // 如果剩余的字节数小于 (我们前面定义的每次发送的字节数) 则按照剩余字节数发送  否则 按照
(我们前面定义的每次发送的字节数)发送
                    long bytesToSend = (totalBytesSent + sendChunkSizeBytes < stream.Length ? sendChunkSizeBytes : stream.Length - totalBytesSent);

                  
                    StreamTools.StreamSendWrapper streamWrapper = new StreamTools.StreamSendWrapper(safeStream, totalBytesSent, bytesToSend);
//我们希望记录包的顺序号  用于在接收端对应数据文件和数据接收文件
                    long packetSequenceNumber;
                    //发送数据文件
                    connection.SendObject("PartialFileData", streamWrapper, sendFileOptions, out packetSequenceNumber);
                     
                   //发送数据文件相对应的信息   (把包的顺序号记录在 SendInfo类中)
                    connection.SendObject("PartialFileDataInfo", new SendInfo(fileID, shortFileName, destFilePath, stream.Length, totalBytesSent, packetSequenceNumber), sendFileOptions);

                    totalBytesSent += bytesToSend;

                    //更新已经发送的字节的属性
                    SentBytes += bytesToSend;

                    
                    FileTransProgress.Raise(this, new FTProgressEventArgs(FileID, SizeBytes, totalBytesSent));

                    //Thread.Sleep(30);
                    if (!((this.fileTransOptions.SleepSpan <= 0) || this.canceled))
                    {
                        Thread.Sleep(this.fileTransOptions.SleepSpan);
                    }

                } while ((totalBytesSent < stream.Length) && !this.canceled);

                if (!this.canceled)
                { 
                    FileTransCompleted.Raise(this, new FTCompleteEventArgs(fileID));
                }
                else
                {
                    //应该发送一个消息给对方,告诉对方文件中断☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 
                    FileTransDisruptted.Raise(this, new FTDisruptEventArgs(FileID, FileTransFailReason.Error));
                }
 
            }
            catch (CommunicationException ex)
            {
                //If there is a communication exception then we just write a connection
                //closed message to the log window
                //AddLineToLog("Failed to complete send as connection was closed.");
                LogTools.LogException(ex, "SendFile.StartSendFile");
                FileTransDisruptted.Raise(this, new FTDisruptEventArgs(FileID, FileTransFailReason.Error));

            }
            catch (Exception ex)
            {
                LogTools.LogException(ex, "SendFile.StartSendFile");
                FileTransDisruptted.Raise(this, new FTDisruptEventArgs(FileID, FileTransFailReason.Error));
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        } 

        //取消文件的发送
        public void Cancel(FileTransFailReason disrupttedType)
        {
            try
            {
                this.canceled = true;

                this.fileTransDisrupttedType = disrupttedType;

                FileTransDisruptted.Raise(this, new FTDisruptEventArgs(FileID, FileTransFailReason.Error));
            }
            catch (Exception ex)
            {
                LogTools.LogException(ex, "SendFile.Cancel");
            }
            
        }


    }
   
}
复制代码

 

www.networkcomms.cn

www.cnblogs.com/networkcomms 编辑

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

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

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

 

相关文章:

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

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

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值