异步TCP客户端实现断线自动重连
在网上找了一个例子,测试发现了一些问题,主要是服务端没有开启,客户端就开启失败,物理网络断开后,无法自动连接。
修改后客户端实现了,被服务端踢下线,自动重连,等待服务端开启后,自动连接,物理网络断开恢复后,自动重连功能,亲自测试,功能完整。
客户端需要心跳发送,不然,物理网络断开恢复后,自动重连功能不能实现。
调用TCP客户端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Timers;
using LJF;
class Program
{
private static string _ip = "192.168.0.10";
private static int _port = 8000;
static void Main(string[] args)
{
AsyncTcpClient lJF = new AsyncTcpClient();
lJF.ConnectServer(_ip, _port);
while (true)
{
Thread.Sleep(1000);
lJF.SendMsg("heartbeat");
}
}
}
异步TCP客户端
/***********************************
* Description:异步TCP客户端
* Mountpoint:这是一个单例脚本,无需挂载,直接调用即可
* Date:2019.06.25
* Version:unity版本2017.2.0f3
* Author:LJF
***********************************/
using System.Net;
using System;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace LJF
{
//规范命名、添加注释、合理封装、限制访问权限
public class AsyncTcpClient
{
private string ip1;
private int port1;
byte[] ReadBytes = new byte[1024 * 1024];
public static bool isWrite = false;
//单例
public static AsyncTcpClient Instance
{
get
{
if (instance == null)
{
instance = new AsyncTcpClient();
}
return instance;
}
}
private static AsyncTcpClient instance;
System.Net.Sockets.TcpClient tcpClient;
//连接服务器
public void ConnectServer(string ip, int port)
{
//Debuger.EnableSave = true;
ip1 = ip;
port1 = port;
try
{
tcpClient = new System.Net.Sockets.TcpClient();//构造Socket
tcpClient.BeginConnect(IPAddress.Parse(ip), port, Lianjie, null);//开始异步
}
catch (Exception e)
{
displayDebug("初始化连接错误---," + e.Message);
}
}
//连接判断
void Lianjie(IAsyncResult ar)
{
if (!tcpClient.Connected)
{
displayDebug("判断连接---,服务器未开启,尝试重连。。。。。。");
tcpClient = null;
try
{
ConnectServer(ip1, port1);
}
catch (Exception e)
{
displayDebug("判断连接---从新连接错误," + e.Message);
}
}
else
{
displayDebug("判断连接---,连接上了");
try
{
tcpClient.EndConnect(ar);//结束异步连接
tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
isWrite = true;
}
catch (Exception e)
{
displayDebug("判断连接错误---," + e.Message);
}
}
}
//接收消息
void ReceiveCallBack(IAsyncResult ar)
{
try
{
int len = tcpClient.GetStream().EndRead(ar);//结束异步读取
if (len > 0)
{
string str = Encoding.GetEncoding("GB2312").GetString(ReadBytes, 0, len);
str = Uri.UnescapeDataString(str);
//将接收到的消息写入日志
//Debuger.Log(string.Format("收到主机:{0}发来的消息|{1}", ip1, str));
displayDebug(str);
writerCsv(getTime(str), "log");
tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
}
else
{
tcpClient = null;
displayDebug("接收消息---连接断开,尝试重连。。。。。。");
ConnectServer(ip1, port1);
}
}
catch (Exception e)
{
displayDebug("接收消息错误---," + e.Message);
tcpClient = null;
displayDebug("接收消息错误---网络断开,尝试重连。。。。。。");
ConnectServer(ip1, port1);
}
}
//发送消息
public void SendMsg(string msg)
{
try
{
if (tcpClient != null && tcpClient.Client.Connected)
{
byte[] msgBytes = Encoding.GetEncoding("GB2312").GetBytes(msg);
tcpClient.GetStream().BeginWrite(msgBytes, 0, msgBytes.Length, (ar) =>
{
tcpClient.GetStream().EndWrite(ar);//结束异步发送
}, null);//开始异步发送
}
else
{
displayDebug("发送消息---,网络断开,尝试重连。。。。。。");
}
}
catch (Exception e)
{
displayDebug("发送消息错误---," + e.Message);
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Close()
{
if (tcpClient != null && tcpClient.Client.Connected)
tcpClient.Close();
if (!tcpClient.Client.Connected)
{
tcpClient.Close();//断开挂起的异步连接
}
}
private void writerCsv(String data, string name)
{
try
{
string mTime = DateTime.Now.ToString("yyyyMMdd");
//string path = System.AppDomain.CurrentDomain.BaseDirectory +"login\\"+ mTime + name + ".csv";
//获取当前文件夹路径
string currPath = System.AppDomain.CurrentDomain.BaseDirectory;
//检查是否存在文件夹
string subPath = currPath + "\\login\\";
if (false == System.IO.Directory.Exists(subPath))
{
//创建文件夹
System.IO.Directory.CreateDirectory(subPath);
}
subPath += mTime + name + ".csv";
FileStream fs = new FileStream(subPath, FileMode.Append);//文本加入不覆盖
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);//转码
sw.WriteLine(data);
//清空缓冲区
sw.Flush();
//关闭流
sw.Close();
fs.Close();
}
catch (Exception)
{
displayDebug("数据保存失败!");
}
}
private void displayDebug(string msg)
{
string log = getTime(msg);
Console.WriteLine(log);
}
private string getTime(string msg)
{
string mTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
mTime += " : ";
mTime += msg;
return mTime;
}
}
}