using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.ComponentModel; using System.Text.RegularExpressions; using System.IO; using System.Xml.Serialization; using FObjBase; namespace OBJ_FileBus { public class Server : INotifyPropertyChanged { private string sMsg; public string Msg { get { return sMsg; } set { sMsg = value; if (this.PropertyChanged != null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Msg")); } } } /// <summary> /// 根路径 如 System.Environment.CurrentDirectory 不包含最后的"\\" /// </summary> public string RootPath { set; get; } /// <summary> /// 文件系统读写 /// </summary> FileSystemInfoRW mFileSystemInfo = new FileSystemInfoRW(); public class ClientInfo { //public IPEndPoint ep; public IFConn conn=null;// 连接的 ID public UInt32 destid;// 远端的 ID public int CompareTo(ClientInfo client) { if ((client.conn == conn) && (client.destid == destid)) { return 0; } else if (client.conn == conn) { return 1; } //else if (client.ep.ToString() == ep.ToString()) //{ // return 2; //} else { return -1; } } } /// <summary> /// 客户端推送设置,所有客户都在里面,对于不需要推送的,List(string).Count=0 /// </summary> Dictionary<ClientInfo, List<string>> mClientPushEn = new Dictionary<ClientInfo, List<string>>(); /// <summary> /// 用于调试,需要推送的文件,上一次的最后写入时间 /// </summary> Dictionary<string, DateTime> mLastWriteTime = new Dictionary<string, DateTime>(); private delegate void FuncHandle(ClientInfo client, Message message); Dictionary<string, FuncHandle> m_service = new Dictionary<string, FuncHandle>(); public Server(string rootpath) { RootPath = rootpath; m_service.Add("readinfo", new FuncHandle(ReadInfo)); m_service.Add("read", new FuncHandle(Read)); m_service.Add("write", new FuncHandle(Write)); m_service.Add("addpush", new FuncHandle(AddPush)); m_service.Add("rmpush", new FuncHandle(RmPush)); m_service.Add("rm", new FuncHandle(Rm)); PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD, new PollModule.PollHandler(OnPoll)); } /// <summary> /// 用于测试,定期检查哪个需要推送的文件,被更新了。 /// </summary> /// <returns></returns> void OnPoll() { var path = from p in mLastWriteTime.AsEnumerable() where p.Value < FileSystemInfoRW.GetLastWriteTime(GetAbsPath(p.Key)) select p; for (int i = 0; i < path.Count(); i++) { string k = path.ElementAt(i).Key; mLastWriteTime[k] = FileSystemInfoRW.GetLastWriteTime(GetAbsPath(k)); PushMsg(k); } } /// <summary> /// 获取绝对路径 /// </summary> /// <param name="path"></param> /// <returns></returns> private string GetAbsPath(string path) { if (path.StartsWith(@"\")) { path = path.Substring(1); } if (string.IsNullOrEmpty(RootPath)) { if (string.IsNullOrEmpty(path)) { return @"."; } else { return path; } } else { return RootPath + @"\" + path; } } #region 功能 public delegate void SendMessageEventHandler(ClientInfo client, byte[] buf); public event SendMessageEventHandler SendMessageEvent; private void Return(ClientInfo client, Message message) { Stream fStream = new MemoryStream(); XmlSerializer xmlFormat = new XmlSerializer( typeof(Message), new Type[] { typeof(MessageArgs), typeof(FileOptMessageArgs), typeof(RetMessageArgs), typeof(ReadInfoRetMessageArgs), typeof(ReadParamMessageArgs), typeof(ReadRetMessageArgs), typeof(WriteParamMessageArgs), typeof(WriteRetMessageArgs), typeof(PushParamMessageArgs), typeof(PushMessageArgs) });//创建XML序列化器,需要指定对象的类型 xmlFormat.Serialize(fStream, message); fStream.Seek(0, SeekOrigin.Begin); byte[] buf=new byte[fStream.Length]; fStream.Read(buf, 0, (int)fStream.Length); fStream.Close(); if (SendMessageEvent != null) SendMessageEvent(client, buf); } /// <summary> /// 功能号分发 /// </summary> /// <param name="ADUBuffer"></param> /// <param name="offset"></param> /// <returns></returns> public void RequestService(ClientInfo client, byte[] order_bytes, out byte[] retdata) { //DateTime dt1 = DateTime.Now; //转换为xml 解码 Message message = Message.Bytes2Message(order_bytes); //获取指令 string order = message.order; retdata = null; if (m_service.ContainsKey(order)) { m_service[order](client, message); retdata = message.ToBytes(); } //DateTime dt2 = DateTime.Now; //System.Diagnostics.Debug.WriteLine((dt2 - dt1).TotalMilliseconds.ToString()); } private void ReadInfo(ClientInfo client, Message message ) { //uint16 order_len 指令字符串长度 //N bytes order 指令字符串 //order 格式 //"readinfo" //path路径 //如 readinfo sysparam.ini //获取文件路径 FileOptMessageArgs args = (FileOptMessageArgs)message.args; string path = args.path; ReadInfoRetMessageArgs ret_args = new ReadInfoRetMessageArgs(); message.args = ret_args; ret_args.path = path; if(FileSystemInfoRW.GetInfo( GetAbsPath(path), out ret_args.fileattr, out ret_args.createtime, out ret_args.lastwritetime, out ret_args.size)) { ret_args.errno = ERRNO.OK; } else { ret_args.errno = ERRNO.NOEXIST; } return; } private void Read(ClientInfo client, Message message ) { //获取文件路径 ReadParamMessageArgs args = (ReadParamMessageArgs)message.args; string path = args.path; ReadRetMessageArgs ret_args = new ReadRetMessageArgs(); message.args = ret_args; byte[] filecontent_bytes; UInt32 filesize=0; FileSystemInfoRW.OptFileContentResult ret = mFileSystemInfo.GetContent( GetAbsPath(path), ref args.guid, args.package_no, args.package_size, out filecontent_bytes, out filesize); ret_args.path = path; int s; FileSystemInfoRW.GetInfo( GetAbsPath(path), out ret_args.fileattr, out ret_args.createtime, out ret_args.lastwritetime, out s); ret_args.filesize = filesize; ret_args.package_size = args.package_size; ret_args.package_no = args.package_no; ret_args.filecontent = filecontent_bytes; ret_args.guid = args.guid; if (ret == FileSystemInfoRW.OptFileContentResult.OK) { ret_args.errno = ERRNO.OK; } else if(ret == FileSystemInfoRW.OptFileContentResult.Doing) { ret_args.errno = ERRNO.DOING; } else if (ret == FileSystemInfoRW.OptFileContentResult.NoExist) { ret_args.errno = ERRNO.NOEXIST; } else//if (ret == FileSystemInfoRW.OptFileContentResult.GUIDErr) { ret_args.errno = ERRNO.ERROR; } return; } private void Write(ClientInfo client, Message message ) { WriteParamMessageArgs args = message.args as WriteParamMessageArgs; string path = args.path; FileSystemInfoRW.OptFileContentResult ret = mFileSystemInfo.SetFileContent( GetAbsPath(path), ref args.guid, args.filesize, args.package_size, args.package_no, args.filecontent); WriteRetMessageArgs ret_args = new WriteRetMessageArgs(); message.args = ret_args; ret_args.path = path; ret_args.guid = args.guid; ret_args.createtime = DateTime.MinValue; ret_args.lastwritetime = DateTime.Now; if (ret == FileSystemInfoRW.OptFileContentResult.OK) { //推送 PushMsg(path); ret_args.errno = ERRNO.OK; int s; FileSystemInfoRW.GetInfo( GetAbsPath(path), out ret_args.fileattr, out ret_args.createtime, out ret_args.lastwritetime, out s); } else if (ret == FileSystemInfoRW.OptFileContentResult.Doing) { ret_args.errno = ERRNO.DOING; } else if (ret == FileSystemInfoRW.OptFileContentResult.NoExist) { ret_args.errno = ERRNO.NOEXIST; } else if (ret == FileSystemInfoRW.OptFileContentResult.CanntWrite) { ret_args.errno = ERRNO.ERROR; } } private void AddPush(ClientInfo client, Message message ) { //uint16 order_len 指令字符串长度 //N bytes order 指令字符串 //order 格式 //"addpush" //path 路径,多个路径以 ; 隔开 PushParamMessageArgs args = message.args as PushParamMessageArgs; RegistPush(client, args.path); PushRetMessageArgs ret_args = new PushRetMessageArgs(); message.args = ret_args; ret_args.path = args.path; ret_args.errno = ERRNO.OK; } private void RmPush(ClientInfo client, Message message ) { PushParamMessageArgs args = message.args as PushParamMessageArgs; var cl = from cpe in mClientPushEn where cpe.Key.CompareTo(client) == 0 select cpe; List<string> plist; if (cl.Count() > 0) { plist = cl.First().Value; if (string.IsNullOrEmpty(args.path)) { //没有路径,全删除 plist.Clear(); } else { string path = args.path; if (plist.Contains(path)) plist.Remove(path); } } PushRetMessageArgs ret_args = new PushRetMessageArgs(); message.args = ret_args; ret_args.path = args.path; ret_args.errno = ERRNO.OK; } private void Rm(ClientInfo client, Message message ) { FileOptMessageArgs args = (FileOptMessageArgs)message.args; string path = args.path; string path2 = GetAbsPath(path); if (System.IO.Directory.Exists(path2)) { System.IO.Directory.Delete(path2); } else if (System.IO.File.Exists(path2)) { System.IO.File.Delete(path2); } //推送 PushMsg(System.IO.Path.GetDirectoryName(path)); RetMessageArgs ret_args = new RetMessageArgs(); message.args = ret_args; ret_args.errno = ERRNO.OK; ret_args.path = path; } /// <summary> /// path 为相对路径 /// </summary> /// <param name="path"></param> /// <returns></returns> void PushMsg(string path) { var need = from _ps in mClientPushEn.AsEnumerable() where _ps.Value.Contains(path) select _ps.Key; if (need.Count() > 0)//需要推送 { PushMessageArgs ret_args = new PushMessageArgs(); ret_args.path = path; FileSystemInfoRW.GetInfo( GetAbsPath(path), out ret_args.fileattr, out ret_args.createtime, out ret_args.lastwritetime, out ret_args.size); Message message = new Message() { order = "push", args = ret_args }; foreach (ClientInfo client in need) { if (client.conn == null) { FileChangedEvent(this, new FileChangedEventArgs() { path = path, fileattr = ret_args.fileattr, modified_dt = ret_args.lastwritetime }); } else { Return(client, message); } } } } public void ClientRemove(ClientInfo client) { var cl = from cpe in mClientPushEn where cpe.Key.CompareTo(client)>=0 select cpe.Key; for (int i = 0; i < cl.Count(); i++) { ClientInfo ci = cl.ElementAt(i); mClientPushEn.Remove(ci); } } public void RegistPush(ClientInfo client, string path) { var cl = from cpe in mClientPushEn where cpe.Key.CompareTo(client) == 0 select cpe; List<string> plist; if (cl.Count() > 0) { plist = cl.First().Value; } else { plist = new List<string>(); mClientPushEn.Add(client, plist); } if (plist.Contains(path) == false) plist.Add(path); if (!mLastWriteTime.ContainsKey(path)) { mLastWriteTime.Add(path, FileSystemInfoRW.GetLastWriteTime(GetAbsPath(path))); } } public class FileChangedEventArgs:EventArgs { /// <summary> /// 路径 /// </summary> public string path; /// <summary> /// 文件类型 /// </summary> public FileAttributes fileattr; /// <summary> /// 修改时间 /// </summary> public DateTime modified_dt; } public delegate void FileChangedEventHandler(object sender, FileChangedEventArgs e); public event FileChangedEventHandler FileChangedEvent; #endregion #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion } }