/****************************** * 说明:下载文件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 { /// /// 下载文件Socket通讯协议 /// public class DownloadSocketProtocol : BaseSocketProtocol { private bool _sendFile; private int _packetSize; private byte[] _readBuffer; private string _fileName; private FileStream _fileStream; /// /// 文件名 /// /// The name of the file. 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); } } /// /// 说明:关闭 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public override void Close() { base.Close(); _fileName = ""; _sendFile = false; if (_fileStream != null) { _fileStream.Close(); _fileStream = null; } lock (_asyncSocketServer) { _asyncSocketServer.DownloadSocketProtocolMgr.Remove(this); } } /// /// 说明:处理分完包的数据,子类从这个方法继承 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The buffer. /// The offset. /// The count. /// true if XXXX, false otherwise. 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; } } /// /// 说明:字符串转换对应下载命令 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The command. /// DownloadSocketCommand. 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; } /// /// 说明:检查是否登录 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The command. /// true if XXXX, false otherwise. public bool CheckLogined(DownloadSocketCommand command) { if ((command == DownloadSocketCommand.Login) | (command == DownloadSocketCommand.Active)) return true; else return _logined; } /// /// 说明:获取目录 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// true if XXXX, false otherwise. 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(); } /// /// 说明:获取文件列表 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// true if XXXX, false otherwise. 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(); } /// /// 说明:下载文件 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// true if XXXX, false otherwise. 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(); } /// /// 说明:检测文件是否正在使用中,如果正在使用中则检测是否被上传协议占用,如果占用则关闭,true表示正在使用中,并没有关闭 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// Name of the file. /// true if XXXX, false otherwise. 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; } /// /// 说明:发送数据 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// true if XXXX, false otherwise. 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; } } /// /// 下载文件管理类 /// public class DownloadSocketProtocolMgr : Object { private List _list; public DownloadSocketProtocolMgr() { _list = new List(); } /// /// 说明:获取下载个数 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// System.Int32. public int Count() { return _list.Count; } /// /// 说明:根据index返回指定DownloadSocketProtocol /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The index. /// DownloadSocketProtocol. public DownloadSocketProtocol ElementAt(int index) { return _list.ElementAt(index); } /// /// 说明:添加 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The value. public void Add(DownloadSocketProtocol value) { _list.Add(value); } /// /// 说明:移除 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The value. public void Remove(DownloadSocketProtocol value) { _list.Remove(value); } } }