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 版本的源碼下載