解决方案 »
- VS2010安装失败
- Process的StandardInput对获取的进程怎么用
- C#求ACCESS中浮点数的平均值
- DataGridView 中不能显示图片的问题
- 关于不规则型状Datagrid的问题..高分请教!!
- 鼠标在网页上的一行字上时,IE状态栏上显示它的URL,请问:如何快速得到网页上的链接及其文字?
- Regsvcs DLL时 显示Classes must be public, concrete, have a public default constructor
- java与C#之比较
- 在任务管理器里结束任务怎么才能及时的删除托盘图标
- 如何创建图片的下拉框
- C# webBrowser控件在IE8的电脑上网页显示不完整
- C#串口通信实时数据统计
//处理文件数据 <2>
NetworkComms.AppendGlobalIncomingPacketHandler<byte[]>("PartialFileData", IncomingPartialFileData);
//处理文件信息 <3>
NetworkComms.AppendGlobalIncomingPacketHandler<SendInfo>("PartialFileDataInfo", IncomingPartialFileDataInfo);private void IncomingPartialFileData(PacketHeader header, Connection connection, byte[] data)
{
try
{
SendInfo info = null;
ReceivedFile file = null; //Perform this in a thread safe way
lock (syncLocker)
{
//Extract the packet sequence number from the header
//The header can also user defined parameters
//获取数据包的顺序号
long sequenceNumber = header.GetOption(PacketHeaderLongItems.PacketSequenceNumber); //如果数据信息字典包含 "连接信息" 和 "包顺序号" if (incomingDataInfoCache.ContainsKey(connection.ConnectionInfo) && incomingDataInfoCache[connection.ConnectionInfo].ContainsKey(sequenceNumber))
{
//We have the associated SendInfo so we can add this data directly to the file
//根据顺序号,获取相关SendInfo记录
info = incomingDataInfoCache[connection.ConnectionInfo][sequenceNumber];
//从信息记录字典中删除相关记录
incomingDataInfoCache[connection.ConnectionInfo].Remove(sequenceNumber);
//Check to see if we have already initialised this file
//检查相关连接上的文件是否存在,如果不存在,则添加相关文件{ReceivedFile}
if (!receivedFiles.ContainsKey(info.FileID))
{
ReceivedFile receivedFile = new ReceivedFile(info.FileID, info.Filename, info.FilePath, connection.ConnectionInfo, info.TotalBytes); receivedFile.FileTransCompleted += new Action<string>(this.receivedFile_FileTransCompleted); receivedFiles.Add(info.FileID, receivedFile);
} file = receivedFiles[info.FileID];
}
else
{
//We do not yet have the associated SendInfo so we just add the data to the cache
//如果不包含顺序号,也不包含相关"连接信息",添加相关连接信息
if (!incomingDataCache.ContainsKey(connection.ConnectionInfo))
incomingDataCache.Add(connection.ConnectionInfo, new Dictionary<long, byte[]>());
//在数据字典中添加相关"顺序号"的信息
incomingDataCache[connection.ConnectionInfo].Add(sequenceNumber, data);
}
} //If we have everything we need we can add data to the ReceivedFile
if (info != null && file != null && !file.IsCompleted)
{
file.AddData(info.BytesStart, 0, data.Length, data); //Perform a little clean-up
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)
{
//If an exception occurs we write to the log window and also create an error file
}
}IncomingPartialFileData
private void IncomingPartialFileDataInfo(PacketHeader header, Connection connection, SendInfo info)
{
try
{
byte[] data = null;
ReceivedFile file = null; //Perform this in a thread safe way
lock (syncLocker)
{
//Extract the packet sequence number from the header
//The header can also user defined parameters
//从 SendInfo类中获取相应数据类的信息号 以便可以对应。
long sequenceNumber = info.PacketSequenceNumber; if (incomingDataCache.ContainsKey(connection.ConnectionInfo) && incomingDataCache[connection.ConnectionInfo].ContainsKey(sequenceNumber))
{
//We already have the associated data in the cache
data = incomingDataCache[connection.ConnectionInfo][sequenceNumber];
incomingDataCache[connection.ConnectionInfo].Remove(sequenceNumber); //Check to see if we have already initialised this file
if (!receivedFiles.ContainsKey(info.FileID))
{
ReceivedFile receivedFile = new ReceivedFile(info.FileID, info.Filename, info.FilePath, connection.ConnectionInfo, info.TotalBytes);
receivedFile.FileTransCompleted += new Action<string>(this.receivedFile_FileTransCompleted);
receivedFiles.Add(info.FileID, receivedFile); } file = receivedFiles[info.FileID];
}
else
{
//We do not yet have the necessary data corresponding with this SendInfo so we add the
//info to the cache
if (!incomingDataInfoCache.ContainsKey(connection.ConnectionInfo))
incomingDataInfoCache.Add(connection.ConnectionInfo, new Dictionary<long, SendInfo>()); incomingDataInfoCache[connection.ConnectionInfo].Add(sequenceNumber, info);
}
} //If we have everything we need we can add data to the ReceivedFile
if (data != null && file != null && !file.IsCompleted)
{
file.AddData(info.BytesStart, 0, data.Length, data);
//Perform a little clean-up
file = null;
data = null;
}
else if (data == null ^ file == null)
throw new Exception("Either both are null or both are set. Data is " + (data == null ? "null." : "set.") + " File is " + (file == null ? "null." : "set.") + " File is " + (file.IsCompleted ? "completed." : "not completed."));
}
catch (Exception ex)
{
}
} IncomingPartialFileDataInfo
MainActivity.cs中添加相应的字典变量
//接收文件字典 Dictionary<string, ReceivedFile> receivedFiles = new Dictionary<string, ReceivedFile>();
/// <summary>
/// Incoming partial data cache. Keys are ConnectionInfo, PacketSequenceNumber. Value is partial packet data.
/// </summary>
Dictionary<ConnectionInfo, Dictionary<long, byte[]>> incomingDataCache = new Dictionary<ConnectionInfo, Dictionary<long, byte[]>>(); /// <summary>
/// Incoming sendInfo cache. Keys are ConnectionInfo, PacketSequenceNumber. Value is sendInfo.
/// </summary>
Dictionary<ConnectionInfo, Dictionary<long, SendInfo>> incomingDataInfoCache = new Dictionary<ConnectionInfo, Dictionary<long, SendInfo>>();
using System.Collections.Generic;
using System.Linq;
using System.Text;using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System.IO;
using NetworkCommsDotNet;
using DPSBase;
using Mobile.Entity;namespace Mobile.Client
{
public class ReceivedFile
{
//////传输过程
////public event Action<string, long, long> FileTransProgress;
//////传输完成
public event Action<string> FileTransCompleted;
//////传输中断
////public event Action<string, FileTransDisrupttedType> 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; } //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 ReceivedBytes == SizeBytes; }
} /// <summary>
/// Private object used to ensure thread safety
/// </summary>
object SyncRoot = new object(); /// <summary>
/// A memory stream used to build the file
/// 用来创建文件的数据流
/// </summary>
Stream data; /// <summary>
///Event subscribed to by GUI for updates
/// </summary>
//临时文件流存储的位置
public string TempFilePath = "";
//文件最后的保存路径
public string SaveFilePath = ""; /// <summary>
/// Create a new ReceivedFile
/// </summary>
/// <param name="filename">Filename associated with this file</param>
/// <param name="sourceInfo">ConnectionInfo corresponding with the file source</param>
/// <param name="sizeBytes">The total size in bytes of this file</param>
public ReceivedFile(string fileID, string filename, string filePath, ConnectionInfo sourceInfo, long sizeBytes)
{
string tempSizeBytes = sizeBytes.ToString(); this.fileID = fileID;
this.Filename = filename;
this.SourceInfo = sourceInfo;
this.SizeBytes = sizeBytes; //如果临时文件已经存在,则添加.data后缀 this.TempFilePath = filePath + filename + ".data";
while (File.Exists(this.TempFilePath))
{ this.TempFilePath = this.TempFilePath + ".data";
}
this.SaveFilePath = filePath + filename; //We create a file on disk so that we can receive large files
//我们在硬盘上创建一个文件,使得我们可以接收大的文件
data = new FileStream(TempFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 8 * 1024, FileOptions.DeleteOnClose); } /// <summary>
/// Add data to file
/// 添加数据到文件中
/// </summary>
/// <param name="dataStart">Where to start writing this data to the internal memoryStream</param>
/// <param name="bufferStart">Where to start copying data from buffer</param>
/// <param name="bufferLength">The number of bytes to copy from buffer</param>
/// <param name="buffer">Buffer containing data to add</param>
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); ////EventsHelper.Fire<string, long, long>(this.FileTransProgress, FileID, SizeBytes, ReceivedBytes); if (ReceivedBytes == SizeBytes)
{
data.Flush();
SaveFileToDisk(SaveFilePath);
data.Close();
EventsHelper.Fire<string>(this.FileTransCompleted, FileID);
}
}
catch (Exception exception)
{
//触发文件传输中断事件
//this.FileTransDisruptted(Filename, FileTransDisrupttedType.InnerError); ////EventsHelper.Fire<string, FileTransDisrupttedType>(this.FileTransDisruptted, FileID, FileTransDisrupttedType.InnerError); }
}
}
} private volatile bool canceled; public void Cancel(FileTransFailReason disrupttedType, bool deleteTempFile)
{
try
{
this.canceled = true;
this.data.Flush();
this.data.Close();
this.data = null;
if (deleteTempFile)
{
File.Delete(this.TempFilePath);
}
}
catch (Exception)
{
}
//通知 Receiver取消,并且触发文件传输中断事件
////EventsHelper.Fire<string, FileTransDisrupttedType>(this.FileTransDisruptted, FileID, FileTransDisrupttedType.InnerError);
} /// <summary>
/// Saves the completed file to the provided saveLocation
/// 保存文件到指定位置
/// </summary>
/// <param name="saveLocation">Location to save file</param>
public void SaveFileToDisk(string saveLocation)
{
if (ReceivedBytes != SizeBytes)
throw new Exception("Attempted to save out file before data is complete."); if (!File.Exists(TempFilePath))
throw new Exception("The transferred file should have been created within the local application directory. Where has it gone?"); //File.Delete(saveLocation); //覆盖文件
File.Copy(TempFilePath, saveLocation, true);
} /// <summary>
/// Closes and releases any resources maintained by this file
/// </summary>
public void Close()
{
try
{
data.Dispose();
}
catch (Exception) { } try
{
data.Close();
}
catch (Exception) { }
}
}
}ReceivedFile