底层库
Net.Sz.CFramework
Net.Sz.CFramework 是我自己的底层库,是经过验证的底层库。
包含:
socket tcp协议,
socket http协议线程池,
线程模型,
任务模型,
定时器模型,
日志模块
脚本模块
一些辅助类
接下来一一介绍
这里是华丽丽的分割线
辅助类功能块
1 // 摘要: 2 // 获取当前时间和 1970-01-01 00:00:00 的时间差 3 // 为了和java一致使用的是 UTC 时间 4 public static long CurrentTimeMillis(); 5 // 6 // 摘要: 7 // 获取当前时间所表示的毫秒数 8 public static long CurrentTimeMillis(DateTime dt); 9 public static long CurrentTimeMillis_Java(); 10 // 11 // 摘要: 12 // 获取当前时间所表示的毫秒数 13 public static long CurrentTimeMillis_Java(DateTime dt); 14 // 15 // 摘要: 16 // 将毫秒数转化成当前时间 17 public static DateTime DateNow(long milliseconds); 18 public static DateTime DateNow_Java(long milliseconds); 19 // 20 // 摘要: 21 // yyyy-MM-dd HH:mm:ss:fff: 22 // 23 // 参数: 24 // d: 25 public static string NowString(DateTime d);
后面java函数是输出和java一直的时间函数
1 // 2 // 摘要: 3 // 验证活动是否结束 验证时间:[*][*][20/22][*][10:00-11:59/16:00-17:59] 4 // 第一个是年,,第二个是月,第三个是日期,第四个是星期,第五个是时间, 5 // 每一个参数,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: “2015/2017”表示2015 6 // 或者 2017 7 public static bool VerifyConfigEndTimeStr(DateTime date, string timeStr); 8 9 // 10 // 摘要: 11 // 获取活动结束时间倒计时 验证时间:[*][*][20/22][*][10:00-11:59/16:00-17:59] 12 // 第一个是年,,第二个是月,第三个是日期,第四个是星期,第五个是时间, 13 // 每一个参数,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: “2015/2017”表示2015 14 // 或者 2017 15 // 返回值 -1 表示永久过期,0 表示在时间规则内,大于 0 表示倒计时 16 public static long VerifyDateEndTime(string timeStr); 17 18 // 19 // 摘要: 20 // 获取开始倒计时 验证时间:[*][*][20/22][*][10:00-11:59/16:00-17:59] 21 // 第一个是年,,第二个是月,第三个是日期,第四个是星期,第五个是时间, 22 // 每一个参数,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: “2015/2017”表示2015 23 // 或者 2017 24 // 返回值 -1 表示永久过期,0 表示在时间规则内,大于 0 表示倒计时 25 public static long VerifyDateTime(string timeStr);
时间匹配函数,看到这里后,请不要给我提quartz 因为我只会回答你不同的需求,不同的环境会有不同的使用情况
位运算辅助函数
1 Net.Sz.CFramework.Struct.EnumStatus status2 = new Net.Sz.CFramework.Struct.EnumStatus(1 << 1, 1 << 0);
使用方式和详解请看 状态机
接下来介绍日志组建
本日志组建支持大约输出日志信息的文件名函数名和行号
方法是异步处理的支持写入文件,文件写入格式是每天一个文件。
1 //是否显示控制台打印 2 Net.Sz.CFramework.Log.Logger.LOGCONSOLE = true; 3 //只支持三种格式。控制台输出,info级别和error级别 4 Net.Sz.CFramework.Log.Logger.LOGLEVEL = Net.Sz.CFramework.Log.ENUM_LOGLEVEL.DEBUG; 5 6 Net.Sz.CFramework.Log.Logger.Debug("{0}->{1}", 55, "test"); 7 Net.Sz.CFramework.Log.Logger.Info("{0}->{1}", 55, "test"); 8 Net.Sz.CFramework.Log.Logger.Error("{0}->{1}", 55, "test"); 9 10 //只显示info 11 Net.Sz.CFramework.Log.Logger.LOGLEVEL = Net.Sz.CFramework.Log.ENUM_LOGLEVEL.INFO; 12 13 Net.Sz.CFramework.Log.Logger.Debug("{0}->{1}", 55, "test"); 14 Net.Sz.CFramework.Log.Logger.Info("{0}->{1}", 55, "test"); 15 Net.Sz.CFramework.Log.Logger.Error("{0}->{1}", 55, "test");
大约信息如下
[2016-03-30 15:03:13:9706: Debug:CApp1.Program, Main, 26] 55->test [2016-03-30 15:03:14:0496: Info :CApp1.Program, Main, 27] 55->test [2016-03-30 15:03:14:0536: Error:CApp1.Program, Main, 30] 55->test [2016-03-30 15:03:14:0536: Info :CApp1.Program, Main, 34] 55->test [2016-03-30 15:03:14:0536: Error:CApp1.Program, Main, 36] 55->test
线程模型.
这里包含了线程模型,任务模型和定时器任务模型
1 //是以一个线程执行任务的线程模型 2 long t1 = Net.Sz.CFramework.Threading.ThreadPool.GetThreadModel("test", 1); 3 4 //是以十个线程执行任务的线程模型 5 long t10 = Net.Sz.CFramework.Threading.ThreadPool.GetThreadModel("test", 10); 6 7 //创建一个简单任务 8 Net.Sz.CFramework.Threading.ThreadPool.AddTask(t1, new Net.Sz.CFramework.Threading.TaskModel_Action(() => 9 { 10 Net.Sz.CFramework.Log.Logger.Debug("TaskModel_Action 简单任务"); 11 12 })); 13 14 //创建一个简单的定时器任务,创建一个执行3次,每个2秒执行一次的任务 15 Net.Sz.CFramework.Threading.ThreadPool.AddTimerTask(t1, new Net.Sz.CFramework.Threading.TimerTask_Action(3, 2000, () => 16 { 17 Net.Sz.CFramework.Log.Logger.Debug("TimerTask_Action 简单任务"); 18 19 }));
输出
1 [2016-03-30 15:16:43:2129: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 149] 初始化 < 全局线程线程 > 2 [2016-03-30 15:16:43:3249: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < Back Thread线程_1 > 3 [2016-03-30 15:16:43:3299: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < Back Thread线程_2 > 4 [2016-03-30 15:16:43:3439: Debug:Net.Sz.CFramework.Threading.ThreadModel, AddTimerTask, 200] Back Thread 接手定时器任务 Net.Sz.CFramework.Threading.Timer.GlobTimerEvent 5 [2016-03-30 15:16:43:3589: Info :Net.Sz.CFramework.Threading.TimerThread, .ctor, 47] 初始化 < timer 线程 > 6 [2016-03-30 15:16:43:3719: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 149] 初始化 < test线程 > 7 [2016-03-30 15:16:43:3849: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_1 > 8 [2016-03-30 15:16:43:3899: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_2 > 9 [2016-03-30 15:16:43:4059: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_3 > 10 [2016-03-30 15:16:43:4099: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_4 > 11 [2016-03-30 15:16:43:4159: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_5 > 12 [2016-03-30 15:16:43:4249: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_6 > 13 [2016-03-30 15:16:43:4359: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_7 > 14 [2016-03-30 15:16:43:4399: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_8 > 15 [2016-03-30 15:16:43:4469: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_9 > 16 [2016-03-30 15:16:43:4559: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < test线程_10 > 17 [2016-03-30 15:16:43:4649: Debug:CApp1.Program, <Main>b__0, 23] TaskModel_Action 简单任务 18 [2016-03-30 15:16:43:4659: Debug:Net.Sz.CFramework.Threading.ThreadModel, AddTimerTask, 200] test 接手定时器任务 Net.Sz.CFramework.Threading.TimerTask_Action 19 [2016-03-30 15:16:43:4729: Debug:CApp1.Program, <Main>b__1, 30] TimerTask_Action 简单任务 20 [2016-03-30 15:16:45:4820: Debug:CApp1.Program, <Main>b__1, 30] TimerTask_Action 简单任务 21 [2016-03-30 15:16:47:4921: Debug:CApp1.Program, <Main>b__1, 30] TimerTask_Action 简单任务
Socket Tcp组建
tcp监听需要实现IIOSessionHandler接口
1 // 摘要: 2 // http监听处理 3 // @author 失足程序员 4 // @Blog http://www.cnblogs.com/ty408/ 5 // @mail 492794628@qq.com 6 // @phone 13882122019 7 public interface IIOSessionHandler 8 { 9 // 摘要: 10 // 新建链接 11 // 12 // 参数: 13 // session: 14 void channelActive(IOSession session); 15 // 16 // 摘要: 17 // 链接闲置状态 18 // 19 // 参数: 20 // session: 21 void channelInactive(IOSession session); 22 // 23 // 摘要: 24 // 有消息,请注意消息是多线程处理的。也许你前一个消息没有处理完成,后一个消息已经来了 25 // 26 // 参数: 27 // session: 28 // 29 // buffer: 30 void channelRead(IOSession session, byte[] buffer); 31 // 32 // 摘要: 33 // 链接断开 34 // 35 // 参数: 36 // session: 37 void channelUnregistered(IOSession session, params string[] obj); 38 // 39 // 摘要: 40 // 链接发送异常 41 // 42 // 参数: 43 // session: 44 // 45 // ex: 46 void exceptionCaught(IOSession session, Exception ex); 47 }
1 //客户端和服务器都需要这个处理接口实现 2 Net.Sz.CFramework.Netty.NettyPool.SessionHandler = new MySessionHandler(); 3 //创建对ip127.0.0.1端口9527的tcp监听,使用一个线程处理这个监听的io信息 4 Net.Sz.CFramework.Netty.NettyPool.AddTcpBind("127.0.0.1", 9527, 1); 5 //创建对服务器连接 6 Net.Sz.CFramework.Netty.Tcp.NettyClient client = new Net.Sz.CFramework.Netty.Tcp.NettyClient("127.0.0.1", 9527); 7 client.Connect();
需要特别注意public void channelRead(Net.Sz.CFramework.Netty.IOSession session, byte[] buffer)
这个函数收到的消息的字节数组是一个完整的独立包
1 #pragma once 2 #include "stdafx.h" 3 #include "BufferReader.h" 4 #include "BufferWriter.h" 5 6 7 using namespace System; 8 9 namespace Net{ 10 namespace Sz{ 11 namespace CFramework{ 12 namespace Netty{ 13 namespace Buffer{ 14 15 using namespace System::IO; 16 using namespace System::Collections::Generic; 17 18 /// <summary> 19 /// 字节流书写器 20 /// <para>@author 失足程序员</para> 21 /// <para>@Blog http://www.cnblogs.com/ty408/</para> 22 /// <para>@mail 492794628@qq.com</para> 23 /// <para>@phone 13882122019</para> 24 /// </summary> 25 ref class DefaultMarshalEndian 26 { 27 //用于存储剩余未解析的字节数 28 private: 29 List<Byte>^ _LBuff = gcnew List<Byte>(2); 30 31 //字节数常量一个消息id4个字节 32 const long ConstLenght = 8L; 33 const short ConstStart1 = 0xaa; 34 const short ConstStart2 = 0xbb; 35 36 public: 37 List<array<Byte>^>^ Decoder(array<Byte>^ buff) 38 { 39 if (this->_LBuff->Count > 0) 40 { 41 //拷贝之前遗留的字节 42 this->_LBuff->AddRange(buff); 43 buff = this->_LBuff->ToArray(); 44 this->_LBuff = gcnew List<Byte>(2); 45 } 46 List<array<Byte>^>^ list = gcnew List<array<Byte>^>(); 47 48 BufferReader^ buffers = gcnew BufferReader(buff); 49 50 try 51 { 52 array<Byte>^ _buff; 53 Label_0073: 54 55 //判断本次解析的字节是否满足常量字节数 56 if ((buffers->BaseStream->Length - buffers->BaseStream->Position) < ConstLenght) 57 { 58 _buff = buffers->ReadBytes((int)(buffers->BaseStream->Length - buffers->BaseStream->Position)); 59 this->_LBuff->AddRange(_buff); 60 } 61 else 62 { 63 short tmpStart1 = buffers->ReadInt16(); 64 if (ConstStart1 == tmpStart1)//自定义头相同 65 { 66 short tmpStart2 = buffers->ReadInt16(); 67 if (ConstStart2 == tmpStart2)//自定义头相同 68 { 69 long offset = buffers->ReadInt32(); 70 //剩余字节数大于本次需要读取的字节数 71 if (offset <= (buffers->BaseStream->Length - buffers->BaseStream->Position)) 72 { 73 _buff = buffers->ReadBytes((int)(offset)); 74 list->Add(_buff); 75 goto Label_0073; 76 } 77 else 78 { 79 //剩余字节数刚好小于本次读取的字节数 存起来,等待接受剩余字节数一起解析 80 buffers->BaseStream->Seek(ConstLenght, System::IO::SeekOrigin::Current); 81 _buff = buffers->ReadBytes((int)(buffers->BaseStream->Length - buffers->BaseStream->Position)); 82 this->_LBuff->AddRange(_buff); 83 } 84 } 85 else 86 { 87 //往前推三个字节 88 buffers->BaseStream->Seek(-3, System::IO::SeekOrigin::Current); 89 goto Label_0073; 90 } 91 } 92 else 93 { 94 //往前推一个字节 95 buffers->BaseStream->Seek(-1, System::IO::SeekOrigin::Current); 96 goto Label_0073; 97 } 98 } 99 } 100 catch (Exception^){} 101 finally 102 { 103 buffers->Close(); 104 delete buffers; 105 } 106 return list; 107 } 108 109 void Encoder(array<Byte>^ msgBuffer, BufferWriter^ %outBuf) 110 { 111 outBuf->Write(ConstStart1); 112 outBuf->Write(ConstStart2); 113 if (msgBuffer != nullptr) 114 { 115 outBuf->Write((Int32)(msgBuffer->Length)); 116 outBuf->Write(msgBuffer); 117 } 118 else 119 { 120 outBuf->Write((Int32)0); 121 } 122 } 123 124 }; 125 } 126 } 127 } 128 } 129 }
解码和编码器
1 [2016-03-30 15:28:55:5178: Info :Net.Sz.CFramework.Netty.Tcp.NettyServer, .ctor, 61] Start Listen Tcp Socket -> 127.0.0.1:9527 2 [2016-03-30 15:28:55:6028: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 149] 初始化 < 全局线程线程 > 3 [2016-03-30 15:28:55:6258: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < Back Thread线程_1 > 4 [2016-03-30 15:28:55:6318: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 151] 初始化 < Back Thread线程_2 > 5 [2016-03-30 15:28:55:6458: Debug:Net.Sz.CFramework.Threading.ThreadModel, AddTimerTask, 200] Back Thread 接手定时器任务 Net.Sz.CFramework.Threading.Timer.GlobTimerEvent 6 [2016-03-30 15:28:55:6648: Info :Net.Sz.CFramework.Threading.TimerThread, .ctor, 47] 初始化 < timer 线程 > 7 [2016-03-30 15:28:55:6798: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 149] 初始化 < Netty Session Pool Thread:127.0.0.1:9527线程 > 8 [2016-03-30 15:28:55:7078: Info :Net.Sz.CFramework.Threading.ThreadModel, .ctor, 149] 初始化 < Netty Session Pool Thread线程 > 9 [2016-03-30 15:28:55:7098: Debug:Net.Sz.CFramework.Threading.ThreadModel, AddTimerTask, 200] Netty Session Pool Thread 接手定时器任务 Net.Sz.CFramework.Netty.CheckIOSessionTimerTask 10 [2016-03-30 15:28:55:7188: Debug:Net.Sz.CFramework.Netty.Tcp.NettyClient, Connect, 48] Try Connect Tcp Socket Remote:127.0.0.1:9527 11 [2016-03-30 15:28:55:7388: Debug:Net.Sz.CFramework.Netty.Tcp.NettyClient, Connect, 51] Connect Tcp Socket Remote Socket RemoteEndPoint:127.0.0.1:9527 LocalEndPoint:127.0.0.1:17669 12 [2016-03-30 15:28:55:7468: Info :Net.Sz.CFramework.Netty.Tcp.NettyServer, AcceptAsync_Async, 43] Create Tcp Socket Remote Socket LocalEndPoint:127.0.0.1:9527 RemoteEndPoint:127.0.0.1:17669
Socket Http监听
需要实现
1 // 摘要: 2 // http监听处理 3 // @author 失足程序员 4 // @Blog http://www.cnblogs.com/ty408/ 5 // @mail 492794628@qq.com 6 // @phone 13882122019 7 public interface IHttpHandler : IBaseScript 8 { 9 // 摘要: 10 // 并发处理的 11 // 12 // 参数: 13 // session: 14 // 连接对象 15 void Action(HttpSession session); 16 }
1 class Program 2 { 3 4 static void Main(string[] args) 5 { 6 //创建login目录的监听,处理程序是LoginHttpHandler,单线程处理请求 7 Net.Sz.CFramework.Netty.NettyPool.AddHttpBind("127.0.0.1", 9527, "login", new LoginHttpHandler(), 1); 8 Console.ReadLine(); 9 } 10 } 11 class LoginHttpHandler : Net.Sz.CFramework.Netty.Http.IHttpHandler 12 { 13 public void Action(Net.Sz.CFramework.Netty.Http.HttpSession session) 14 { 15 session.WriteSuccess(); 16 session.AddBody("Login OK"); 17 session.WriteFlush(); 18 } 19 }
脚步使用功能
使用脚步功能,C#的文件类,*.cs文件类
如果是实现IBaseScript可以放到脚步管理器里面进行查找
如果实现IInitBaseScript接口执行初始化函数;如果没有只实现IInitBaseScript不会放到脚步管理,
// 摘要: // 脚本基类 // @author 失足程序员 // @Blog http://www.cnblogs.com/ty408/ // @mail 492794628@qq.com // @phone 13882122019 public interface IBaseScript // 摘要: // 脚本基类 // 执行init初始化信息 // PS:实现这个接口不会放到脚步缓存集合中,如果需要请实现 IBaseScript // @author 失足程序员 // @Blog http://www.cnblogs.com/ty408/ // @mail 492794628@qq.com // @phone 13882122019 public interface IInitBaseScript { // 摘要: // 卸载脚本 void InitScript(); }
//传入文件路径,可以是相对路径也可以是绝对路径,后面可以传入需要引入的dll文件或者exe文件用于编译和加载 ScriptManager.LoadCSharpFile(new String[] { "" }, "");
这里以我的游戏程序距离
public static List<string> LoadScript() { return ScriptManager.LoadCSharpFile(new string[] { "../../../../Net.Sz.Game.MMOGame.GameServer.Scripts/Src" }, "protobuf-net.dll", "EntityFramework.dll", "MySql.Data.dll", "Net.Sz.Framework.DB.dll", "MySql.Data.Entity.EF6.dll", "Net.Sz.Game.MMOGame.GameMessages.dll", "Net.Sz.Game.MMOGame.GameModel.dll" ); } public static Net.Sz.CFramework.Script.ScriptPool ScriptManager { get; private set; } /// <summary> /// /// </summary> public static void Start() { Net.Sz.CFramework.Struct.SzExtensions.Console_Show("Server", false, true); try { LoadScript(); } catch (Exception) { throw; } }
这是我的底层库支持。望各位大仙多多指教!
对应提供下载.
java 版本的源码下载
/** * * @author 失足程序员 * @Blog http://www.cnblogs.com/ty408/ * @mail 492794628@qq.com * @phone 13882122019 * */ 跪求保留标示符 本程序猿所有博客园相关全套源码奉献 淘宝SVN。特别鸣谢淘宝SVN提供免费仓储。 http://code.taobao.org/svn/flynetwork_csharp/trunk/Flynetwork/BlogTest