本文代碼所有是基於原生,未使用任何框架技術json
//生明一個成功響應的委託時間 public delegate void SuccessDelegate(Response response); //鏈接服務器 public void handshake(SuccessDelegate success) { //定義一個套字節監聽 包含3個參數(IP4尋址協議,流式鏈接,TCP協議) socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //須要獲取文本框中的IP地址 IPAddress ipaddress = IPAddress.Parse(IP); //將獲取的ip地址和端口號綁定到網絡節點endpoint上 IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(Port)); //這裏客戶端套接字鏈接到網絡節點(服務端)用的方法是Connect 而不是Bind socketClient.Connect(endpoint); loop(); //發送握手數據包 clientSendMsg(Global.getHandshakeJson(), success); } //接收服務端發來信息的方法 private void RecMsg() { while (true) //持續監聽服務端發來的消息 { try { //因爲博主業務爲前面四位表明 後續body的長度,因此這裏先取四位 byte[] header = new byte[4]; //將客戶端套接字接收到的數據存入內存緩衝區, 並獲取其長度 int l = c.socketClient.Receive(header); if (l == 0) { LogHelper.info("Connection closed."); handshake((response) => { //連接成功 LogHelper.info("Connect successed."); }); return; } //取上文的值長度 Array.Reverse(header); int length = System.BitConverter.ToInt32(header, 0); byte[] body = new byte[length]; int bl = c.socketClient.Receive(body); String jsonBody = Encoding.ASCII.GetString(body); Response response1 = jsonBody.FromJson<Response>(); //與後端約定爲單數seq爲請求,雙數爲響應 if (response1.seq % 2 == 1) { //這裏處理服務器下發的請求 } else { LogHelper.info("[Receive]" + jsonBody); if (requestList.ContainsKey(response1.seq - 1)) { SuccessDelegate success = requestList[response1.seq - 1]; requestList.Remove(response1.seq - 1); success(response1); } } } catch (SocketException e) { c.isConnected = false; socketClient = null; threadClient = null; LogHelper.info("[Receive] 服務器斷開鏈接,"+e.ToString()); return; } } } //發送信息到服務端的方法 public void clientSendMsg(Request request, SuccessDelegate success) { if (!isConnected) { return; } String json = JSONWriter.ToJson(request); Int32 len = json.Length; byte[] length = System.BitConverter.GetBytes(len); Array.Reverse(length); byte[] data = Encoding.ASCII.GetBytes(json); byte[] byteData = new byte[length.Length + data.Length]; length.CopyTo(byteData, 0); data.CopyTo(byteData, length.Length); //調用客戶端套接字發送字節數組 socketClient.Send(byteData); LogHelper.info("[Send]" + JSONWriter.ToJson(request)); requestList[request.seq] = success; }
class Request { public String cmd; //指令 public String version; //版本號 public int seq; //表明包序列號 從1開始天然2增加 確定爲奇數 next_seq = pre_seq + 2 public Dictionary<string, object> cmd_body; //主內容 } class Response { public int code; //是否成功 public String msg; //信息 public int seq; //表明包序列號 爲請求序列號+1 public Dictionary<string, object> resp_body; //主內容 }
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Thread threadClient; //建立一個線程 用於監聽服務端發來的消息 threadClient = new Thread(handshake); //將線程設置爲與後臺同步 threadClient.IsBackground = true; //啓動線程 threadClient.Start(); Application.Run(new LoginForm()); } static void handshake() { //step1:與服務器鏈接,併發送握手數據包 TcpConnection.getInstance().handshake((response) => { //服務器響應握手數據包,這裏沒有判斷,使用者能夠根據自身狀況處理,連接成功 LogHelper.info("Connect successed."); }); while (true) { //每四分鐘檢測一次是否鏈接,若是沒有鏈接,重連服務器 while (!TcpConnection.getInstance().connected()) { Thread.Sleep(4 * 60 * 1000); TcpConnection.getInstance().handshake((response) => { //連接成功 LogHelper.info("Connect successed."); }); } //每四分鐘檢測一次是否鏈接,若是鏈接,則發送心跳包到服務器 while (TcpConnection.getInstance().connected()) { Thread.Sleep(4 * 60 * 10000); TcpConnection.getInstance().clientSendMsg(Global.getHeartJson(), (response) => { //連接成功 LogHelper.info("Heart send successed."); }); } } }