ab56a9bcf7
SVN-Revision: r240
452 lines
18 KiB
C#
452 lines
18 KiB
C#
/******************************
|
|
* 说明:下载文件Socket通讯协议
|
|
* 创建人:龚宇超
|
|
* 创建日期:2018-01-23
|
|
* 修改人:
|
|
* 修改日期:
|
|
* 修改备注:
|
|
* 版本:1.0.0.0
|
|
******************************/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Net.Sockets;
|
|
using System.IO;
|
|
|
|
namespace Lskj.SocketService
|
|
{
|
|
/// <summary>
|
|
/// 下载文件Socket通讯协议
|
|
/// </summary>
|
|
public class DownloadSocketProtocol : BaseSocketProtocol
|
|
{
|
|
private bool _sendFile;
|
|
private int _packetSize;
|
|
private byte[] _readBuffer;
|
|
private string _fileName;
|
|
|
|
private FileStream _fileStream;
|
|
/// <summary>
|
|
/// 文件名
|
|
/// </summary>
|
|
/// <value>The name of the file.</value>
|
|
public string FileName { get { return _fileName; } }
|
|
|
|
public DownloadSocketProtocol(AsyncSocketServer asyncSocketServer, AsyncSocketUserToken asyncSocketUserToken)
|
|
: base(asyncSocketServer, asyncSocketUserToken)
|
|
{
|
|
_socketFlag = "Download";
|
|
_fileName = "";
|
|
_fileStream = null;
|
|
_sendFile = false;
|
|
_packetSize = 64 * 1024;
|
|
lock (_asyncSocketServer.DownloadSocketProtocolMgr)
|
|
{
|
|
_asyncSocketServer.DownloadSocketProtocolMgr.Add(this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>说明:关闭</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
public override void Close()
|
|
{
|
|
base.Close();
|
|
_fileName = "";
|
|
_sendFile = false;
|
|
if (_fileStream != null)
|
|
{
|
|
_fileStream.Close();
|
|
_fileStream = null;
|
|
}
|
|
lock (_asyncSocketServer)
|
|
{
|
|
_asyncSocketServer.DownloadSocketProtocolMgr.Remove(this);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:处理分完包的数据,子类从这个方法继承</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="buffer">The buffer.</param>
|
|
/// <param name="offset">The offset.</param>
|
|
/// <param name="count">The count.</param>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public override bool ProcessCommand(byte[] buffer, int offset, int count)
|
|
{
|
|
DownloadSocketCommand command = StrToCommand(_incomingDataParser.Command);
|
|
_outgoingDataAssembler.Clear();
|
|
_outgoingDataAssembler.AddResponse();
|
|
_outgoingDataAssembler.AddCommand(_incomingDataParser.Command);
|
|
if (!CheckLogined(command)) //检测登录
|
|
{
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.UserHasLogined, "");
|
|
return DoSendResult();
|
|
}
|
|
if (command == DownloadSocketCommand.Login)
|
|
return DoLogin();
|
|
else if (command == DownloadSocketCommand.Active)
|
|
return DoActive();
|
|
else if (command == DownloadSocketCommand.Dir)
|
|
return DoDir();
|
|
else if (command == DownloadSocketCommand.FileList)
|
|
return DoFileList();
|
|
else if (command == DownloadSocketCommand.Download)
|
|
return DoDownload();
|
|
else
|
|
{
|
|
Program.Logger.Error("Unknow command: " + _incomingDataParser.Command);
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:字符串转换对应下载命令</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="command">The command.</param>
|
|
/// <returns>DownloadSocketCommand.</returns>
|
|
public DownloadSocketCommand StrToCommand(string command)
|
|
{
|
|
if (command.Equals(ProtocolKey.Active, StringComparison.CurrentCultureIgnoreCase))
|
|
return DownloadSocketCommand.Active;
|
|
else if (command.Equals(ProtocolKey.Login, StringComparison.CurrentCultureIgnoreCase))
|
|
return DownloadSocketCommand.Login;
|
|
else if (command.Equals(ProtocolKey.Dir, StringComparison.CurrentCultureIgnoreCase))
|
|
return DownloadSocketCommand.Dir;
|
|
else if (command.Equals(ProtocolKey.FileList, StringComparison.CurrentCultureIgnoreCase))
|
|
return DownloadSocketCommand.FileList;
|
|
else if (command.Equals(ProtocolKey.Download, StringComparison.CurrentCultureIgnoreCase))
|
|
return DownloadSocketCommand.Download;
|
|
else
|
|
return DownloadSocketCommand.None;
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:检查是否登录</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="command">The command.</param>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public bool CheckLogined(DownloadSocketCommand command)
|
|
{
|
|
if ((command == DownloadSocketCommand.Login) | (command == DownloadSocketCommand.Active))
|
|
return true;
|
|
else
|
|
return _logined;
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:获取目录</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public bool DoDir()
|
|
{
|
|
string parentDir = "";
|
|
if (_incomingDataParser.GetValue(ProtocolKey.ParentDir, ref parentDir))
|
|
{
|
|
if (parentDir == "")
|
|
parentDir = SocketApp.FileDirectory;
|
|
else
|
|
parentDir = Path.Combine(SocketApp.FileDirectory, parentDir);
|
|
if (Directory.Exists(parentDir))
|
|
{
|
|
string[] subDirectorys = Directory.GetDirectories(parentDir, "*", SearchOption.TopDirectoryOnly);
|
|
_outgoingDataAssembler.AddSuccess();
|
|
char[] directorySeparator = new char[1];
|
|
directorySeparator[0] = Path.DirectorySeparatorChar;
|
|
for (int i = 0; i < subDirectorys.Length; i++)
|
|
{
|
|
string[] directoryName = subDirectorys[i].Split(directorySeparator, StringSplitOptions.RemoveEmptyEntries);
|
|
_outgoingDataAssembler.AddValue(ProtocolKey.Item, directoryName[directoryName.Length - 1]);
|
|
}
|
|
}
|
|
else
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.DirNotExist, "");
|
|
}
|
|
else
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
|
|
return DoSendResult();
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:获取文件列表</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public bool DoFileList()
|
|
{
|
|
string dirName = "";
|
|
if (_incomingDataParser.GetValue(ProtocolKey.DirName, ref dirName))
|
|
{
|
|
if (dirName == "")
|
|
dirName = SocketApp.FileDirectory;
|
|
else
|
|
dirName = Path.Combine(SocketApp.FileDirectory, dirName);
|
|
if (Directory.Exists(dirName))
|
|
{
|
|
string[] files = Directory.GetFiles(dirName);
|
|
_outgoingDataAssembler.AddSuccess();
|
|
Int64 fileSize = 0;
|
|
for (int i = 0; i < files.Length; i++)
|
|
{
|
|
FileInfo fileInfo = new FileInfo(files[i]);
|
|
fileSize = fileInfo.Length;
|
|
_outgoingDataAssembler.AddValue(ProtocolKey.Item, fileInfo.Name + ProtocolKey.TextSeperator + fileSize.ToString());
|
|
}
|
|
}
|
|
else
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.DirNotExist, "");
|
|
}
|
|
else
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
|
|
return DoSendResult();
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:下载文件</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public bool DoDownload()
|
|
{
|
|
string dirName = string.Empty;
|
|
string fileName = string.Empty;
|
|
if (_incomingDataParser.GetValue(ProtocolKey.DirName, ref dirName) &
|
|
_incomingDataParser.GetValue(ProtocolKey.FileName, ref fileName))
|
|
{
|
|
if (string.IsNullOrWhiteSpace(dirName))
|
|
dirName = SocketApp.FileDirectory;
|
|
else
|
|
dirName = Path.Combine(SocketApp.FileDirectory, dirName);
|
|
fileName = Path.Combine(dirName, fileName);
|
|
Program.Logger.Info("Start download file: " + fileName);
|
|
if (_fileStream != null) //关闭上次传输的文件
|
|
{
|
|
_fileStream.Close();
|
|
_fileStream = null;
|
|
_fileName = "";
|
|
_sendFile = false;
|
|
}
|
|
if (File.Exists(fileName))
|
|
{
|
|
if (!CheckFileInUse(fileName)) //检测文件是否正在使用中
|
|
{
|
|
_fileName = fileName;
|
|
_fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
|
|
_sendFile = true;
|
|
|
|
_outgoingDataAssembler.AddSuccess();
|
|
_outgoingDataAssembler.AddValue(ProtocolKey.FileSize, _fileStream.Length);
|
|
}
|
|
else
|
|
{
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.FileIsInUse, "");
|
|
Program.Logger.Error("Start download file error, file is in use: " + fileName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.FileNotExist, "");
|
|
}
|
|
}
|
|
else
|
|
_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
|
|
|
|
return DoSendResult();
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:检测文件是否正在使用中,如果正在使用中则检测是否被上传协议占用,如果占用则关闭,true表示正在使用中,并没有关闭</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="fileName">Name of the file.</param>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public bool CheckFileInUse(string fileName)
|
|
{
|
|
if (BasicFunc.IsFileInUse(fileName))
|
|
{
|
|
bool result = true;
|
|
lock (_asyncSocketServer.DownloadSocketProtocolMgr)
|
|
{
|
|
DownloadSocketProtocol downloadSocketProtocol = null;
|
|
for (int i = 0; i < _asyncSocketServer.DownloadSocketProtocolMgr.Count(); i++)
|
|
{
|
|
downloadSocketProtocol = _asyncSocketServer.DownloadSocketProtocolMgr.ElementAt(i);
|
|
if (fileName.Equals(downloadSocketProtocol.FileName, StringComparison.CurrentCultureIgnoreCase))
|
|
{
|
|
lock (downloadSocketProtocol.AsyncSocketUserToken) //AsyncSocketUserToken有多个线程访问
|
|
{
|
|
_asyncSocketServer.CloseClientSocket(downloadSocketProtocol.AsyncSocketUserToken);
|
|
}
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:发送数据</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
|
public override bool SendCallback()
|
|
{
|
|
bool result = base.SendCallback();
|
|
if (_fileStream != null)
|
|
{
|
|
if (_sendFile) //发送文件头
|
|
{
|
|
_outgoingDataAssembler.Clear();
|
|
_outgoingDataAssembler.AddResponse();
|
|
_outgoingDataAssembler.AddCommand(ProtocolKey.SendFile);
|
|
_outgoingDataAssembler.AddSuccess();
|
|
_outgoingDataAssembler.AddValue(ProtocolKey.FileSize, _fileStream.Length - _fileStream.Position);
|
|
result = DoSendResult();
|
|
_sendFile = false;
|
|
}
|
|
else
|
|
{
|
|
if (_fileStream.Position < _fileStream.Length) //发送具体数据
|
|
{
|
|
_outgoingDataAssembler.Clear();
|
|
_outgoingDataAssembler.AddResponse();
|
|
_outgoingDataAssembler.AddCommand(ProtocolKey.Data);
|
|
_outgoingDataAssembler.AddSuccess();
|
|
if (_readBuffer == null)
|
|
_readBuffer = new byte[_packetSize];
|
|
else if (_readBuffer.Length < _packetSize) //避免多次申请内存
|
|
_readBuffer = new byte[_packetSize];
|
|
int count = _fileStream.Read(_readBuffer, 0, _packetSize);
|
|
result = DoSendResult(_readBuffer, 0, count);
|
|
}
|
|
else //发送完成
|
|
{
|
|
Program.Logger.Info("End download file: " + _fileName);
|
|
_fileStream.Close();
|
|
_fileStream = null;
|
|
_fileName = "";
|
|
_sendFile = false;
|
|
result = true;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 下载文件管理类
|
|
/// </summary>
|
|
public class DownloadSocketProtocolMgr : Object
|
|
{
|
|
private List<DownloadSocketProtocol> _list;
|
|
public DownloadSocketProtocolMgr()
|
|
{
|
|
_list = new List<DownloadSocketProtocol>();
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:获取下载个数</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <returns>System.Int32.</returns>
|
|
public int Count()
|
|
{
|
|
return _list.Count;
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:根据index返回指定DownloadSocketProtocol</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="index">The index.</param>
|
|
/// <returns>DownloadSocketProtocol.</returns>
|
|
public DownloadSocketProtocol ElementAt(int index)
|
|
{
|
|
return _list.ElementAt(index);
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:添加</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
public void Add(DownloadSocketProtocol value)
|
|
{
|
|
_list.Add(value);
|
|
}
|
|
/// <summary>
|
|
/// <para>说明:移除</para>
|
|
/// <para>创建人:龚宇超</para>
|
|
/// <para>创建日期:2018-01-24 </para>
|
|
/// <para>修改人:</para>
|
|
/// <para>修改日期:</para>
|
|
/// <para>修改备注:</para>
|
|
/// <para>版本:1.0</para>
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
public void Remove(DownloadSocketProtocol value)
|
|
{
|
|
_list.Remove(value);
|
|
}
|
|
}
|
|
}
|