基礎Socket
自強的程序猿們都喜歡搞Socket,而且覺得最好自己來封裝個組件出來,如果再往上,加入某種數據協議,讓上層服務器開發照着此協議走,就是一個小小的框架了。於是,從頭開始,最開始的服務器的雛形與下圖有一些相似。
現在服務器可以通過socket1到n,分別發送二進制數據到達對應的client1到n了,如果服務器的設計到此打住,本文也就到此打住了,但這個的服務器,畢竟離實際可以拿來作某種服務太遙遠了,就於就有了更深層次的封裝和擴展。
兩種封裝和擴展
第一種:保留Socket1到n不變,擴展ListenerServer
例如,現在有一個需求,要服務器發到客戶端的數據內容為某些對象序列化后的JSON文本UTF8轉碼后的二進制,通過繼承ListenerServer,我們可以封裝一個SendJson的方法
public class JsonServer : ListenerServer { public void SendJson(Socket socket, object model) { var javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var json = javaScriptSerializer.Serialize(model); this.SendJson(socket, json); } public void SendJson(Socket socket, string json) { var buffer = Encoding.UTF8.GetBytes(json); socket.Send(buffer); } }
到此,這種設計感覺依然”完美“,如果往上抽象一層,加入某種協議,基礎的ListenerServer的就設計為ListenerServerBase<T> where T:IProtocol,IProtocol形成協議約束。
讓我說,我覺得這種設計基本能解決問題,但職責不單一,會造成上層通訊相關代碼和業務服務API代碼會偶合在一起,無法分離,因為所有返回數據流,都深深依賴於ListenerServer這個對象。假設ListenerServer為IIS,socket1到n為HttpContext,那么我們的業務API代碼就依賴於IIS而不是依賴於HttpContext了,但寫了這么多年Asp.net程序,沒有人能引用IIS程序集,調用IIS.Instance.Response.Write("這是服務器回復的內容“)如此的代碼吧!
第二種
ListenerServer只作監聽,而socket1到n作類似HttpContext一樣封裝,在此且命名為Session會話,如下圖
現在解決剛才的JSON需求的SendJson的方法如下:
public class JsonSession : Session { public void SendJson(object model) { var javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var json = javaScriptSerializer.Serialize(model); this.SendJson(json); } public void SendJson(string json) { var buffer = Encoding.UTF8.GetBytes(json); base.Send(buffer); } }
到這里,感覺邏輯通順多了,得到一個session會話實例,就可以調用session.SendJson(json)了,不依賴於ListenerServer。而基礎ListenerServer可以設計為ListenerServer<T> where T:Session,加入的協議在Session的派生類完成。
本文只代碼作者觀點,如果你想繼續深入第二種擴展方法,可以參考我的一個socket組件:NetworkSocket