本文代码所有是基于原生,未使用任何框架技术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."); }); } } }