您的位置:首页 > 理论基础 > 计算机网络

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

2015-02-02 14:08 846 查看

基于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网络通信的自动升级程序源码分析-客户端接收文件

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐