【转载请注明出处】
本文代码全部是基于原生,未使用任何框架技术
核心代码如下
//生明一个成功响应的委托时间
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;
}
下面是Response结构
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.");
});
}
}
}