基础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的派生类完成。