解决拔掉网线后无法快速诊断是否掉线问题
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System;
using System.Text;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using System.Threading;
namespace MyTcpClient
{
//规范命名、添加注释、合理封装、限制访问权限
public class AsyncTcpClient
{
private string ip1;
private int port1;
private byte[] ReadBytes = new byte[1024];
//单例
private TcpClient tcpClient;
//连接服务器
public void ConnectServer(string ip, int port)
{
//防止多个事例去重复连接
if (isTryingToCon == true)
{
return;
}
ip1 = ip;
port1 = port;
try
{
if (tcpClient != null)
{
tcpClient.Close();
}
tcpClient = new TcpClient();
isTryingToCon = true;
//开始异步
tcpClient.BeginConnect(IPAddress.Parse(ip), port, Lianjie, null);
}
catch (Exception e)
{
}
}
private bool isTryingToCon = false;
//连接判断
private void Lianjie(IAsyncResult ar)
{
if (IsClose)
{
return;
}
try
{
if (tcpClient.Connected == false)
{
SetCon(0);
tcpClient.Close();
tcpClient = new System.Net.Sockets.TcpClient();
//尝试重连。。。。。。;
tcpClient.BeginConnect(IPAddress.Parse(ip1), port1, Lianjie, null);
}
else
{
tcpClient.Client.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 500, 500), null);
//连接上了
isTryingToCon = false;
//结束异步连接
tcpClient.EndConnect(ar);
//读取数据
tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
SetCon(1);
}
}
catch (Exception)
{
}
}
private byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
{
byte[] buffer = new byte[12];
BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
return buffer;
}
//接收消息
private void ReceiveCallBack(IAsyncResult ar)
{
try
{
int len = tcpClient.GetStream().EndRead(ar);//结束异步读取
if (len > 0)
{
MyEventArgs e = new MyEventArgs(ip1, ReadBytes);
_MsgChange(e);
//重置数据,防止旧数据残留
ReadBytes = new byte[512];
tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
}
else
{
//尝试重连。。。。。。"
ConnectServer(ip1, port1);
}
}
catch (Exception e)
{
}
}
//发送消息
public bool SendMsg(string msg)
{
//发送XXXX0001_000000000000_ (没有下划线)
//接收00570002_000000000000_010001020103
try
{
//数据部分
byte[] bt_Data = Encoding.ASCII.GetBytes(msg);
byte[] bt_head = Encoding.ASCII.GetBytes((bt_Data.Length + 4).ToString("0000"));
byte[] bt_send = new byte[bt_Data.Length + 4];
for (int i = 0; i < bt_head.Length; i++)
{
bt_send[i] = bt_head[i];
}
for (int i = 0; i < bt_Data.Length; i++)
{
bt_send[i + 4] = bt_Data[i];
}
//开始异步发送
try
{
tcpClient.GetStream().BeginWrite(bt_send, 0, bt_send.Length, (ar) =>
{
tcpClient.GetStream().EndWrite(ar);//结束异步发送
}, null);
}
catch (Exception ex)
{
string abc = ex.ToString();
}
return true;
}
catch (Exception ex)
{
SetCon(-1);
SetCon(0);
// int a = ex.NativeErrorCode;
//尝试重连。。。。。。"
ConnectServer(ip1, port1);
return false;
}
}
public bool SendMsg(byte[] msg)
{
try
{
//开始异步发送
tcpClient.GetStream().BeginWrite(msg, 0, msg.Length, (ar) =>
{
tcpClient.GetStream().EndWrite(ar);//结束异步发送
}, null);
return true;
}
catch (Exception ex)
{
//尝试重连。。。。。。"
SetCon(-1);
SetCon(0);
ConnectServer(ip1, port1);
return false;
}
}
bool IsClose = false;
/// <summary>
/// 断开连接
/// </summary>
public void Close()
{
IsClose = true;
if (tcpClient != null && (tcpClient.Client == null || tcpClient.Client.Connected))
{
tcpClient.Close();
}
}
public int isConnected = -1;
/// <summary>
/// -1 初始化 0 未连接 1 连接
/// </summary>
/// <param name="_con"></param>
private void SetCon(int _con)
{
if (isConnected != _con)
{
bool rel = false;
if (_con == 1)
{
rel = true;
}
isConnected = _con;
MyEventArgs e = new MyEventArgs(ip1 + "__" + port1.ToString(), rel);
_ConChange(e);
}
}
public void StarPing()
{
Task.Factory.StartNew(() => PingOC());
}
private void PingOC()
{
Ping ping = new Ping();
while (!IsClose)
{
try
{
PingReply pingReply = ping.Send(ip1, 1000);
//网络状态
if (pingReply.Status != IPStatus.Success)
{
SetCon(-1);
SetCon(0);
ConnectServer(ip1, port1);
}
Thread.Sleep(1000);
}
catch (Exception)
{
}
}
}
public class MyEventArgs : EventArgs
{
public string IP;
public bool IsConnetct;
public byte[] Msg;
public MyEventArgs(string iP, byte[] msg)
{
IP = iP;
Msg = msg;
}
public MyEventArgs(string iP, bool iscon)
{
IP = iP;
IsConnetct = iscon;
}
}
//连接状态
public delegate void ConChange(object sender, MyEventArgs args);
public event ConChange OnConChange;
protected virtual void _ConChange(MyEventArgs e)
{
if (OnConChange != null)
{
OnConChange(this, e);
}
}
//收到的消息
public delegate void MsgChange(object sender, MyEventArgs args);
public event MsgChange OnMsgChange;
protected virtual void _MsgChange(MyEventArgs e)
{
if (OnMsgChange != null)
{
OnMsgChange(this, e);
}
}
}
}
调用方法:
AsyncTcpClient sw = new AsyncTcpClient();
sw.ConnectServer("192.168.1.1", 4545);
sw.OnConChange += Sw_OnConChange;
sw.OnMsgChange += Sw_OnMsgChange;
sw.StarPing();
private void Sw_OnConChange(object sender, AsyncTcpClient.MyEventArgs args)
{
if (args.IsConnetct)
{
//已连接
}
else
{
//已断开
}
}
private void Sw_OnMsgChange(object sender, AsyncTcpClient.MyEventArgs args)
{
//接收的信息
string str = Encoding.ASCII.GetString(args.Msg, 0, args.Msg.Length);
str = Uri.UnescapeDataString(str).Replace("\0", "");
}
public void CloseTcp()
{
sw.OnConChange -= Sw_OnConChange;
sw.OnMsgChange -= Sw_OnMsgChange;
sw.Close();
}