【转载请注明出处】
本文代码全部是基于原生,未使用任何框架技术
核心代码如下
//生明一个成功响应的委托时间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(); //与后端约定为单数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;}
下面是Response结构
class Request{ public String cmd; //指令 public String version; //版本号 public int seq; //代表包序列号 从1开始自然2增长 肯定为奇数 next_seq = pre_seq + 2 public Dictionarycmd_body; //主内容}class Response{ public int code; //是否成功 public String msg; //信息 public int seq; //代表包序列号 为请求序列号+1 public Dictionary 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."); }); } }}