Winfor Tcp通信(服务端)
今天给大家讲一下C# 关于Tcp 通信部分,这一块的教程网上一大堆,不过关于掉网,异常断开连接的这部分到是到是没有多少说明,有方法 不过基本上最多的两种方式(1.设置一个超时时间,2.单独整个心跳上报)
我觉得那个不好用,所以就给大家分享一下 第三种方式! 就比如 作为 服务端 能够快速的检测到客户端 掉线,然后做处理。
然后说一下 这个篇文章 只讲 服务端的内容,如果想看完整通信 的建议去看看其他的帖子
1.首先是IP地址 :
作为服务端 首先就是需要自己的IP地址,通过下面函数获取到当前主机多个 ID地址,返回一个列表
/// <summary>
/// 获取本地的IP地址
/// </summary>
/// <returns></returns>
private List<String> GetLocalIPAddress()
{
List<String> AddressIP = new List<string>();
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
AddressIP.Add(_IPAddress.ToString());
}
}
return AddressIP;
}
2.其次就是开启TCP服务
static bool IsTcpStart_ZX = false; //判断TCP是否是否开启 开启状态下有效
IPEndPoint TcpIpep_ZX = null; //连接TCP终端地址
Socket socketSever_ZX = null;
/// <summary>
/// 创建TCP
/// </summary>
/// <param name="ipAddrs"></param>
/// <param name="port"></param>
/// <returns></returns>
private bool creatTcpSever_ZX(string ipAddrs, string port)
{
try
{
TcpIpep_ZX = new IPEndPoint(IPAddress.Parse(ipAddrs), int.Parse(port)); // 本机IP和监听端口号
socketSever_ZX = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketSever_ZX.Bind(TcpIpep_ZX);
socketSever_ZX.Listen(1);
socketSever_ZX.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 1000, 1000), null); //保活时间 用于判断客户端 非正常断开(程序引起的掉线)
IsTcpStart_ZX = true;
/* this.Invoke(new Action(() =>
{
toolStripLabel1.Text = "TCP 服务开启成功!";
}));*/
threadSever_ZX = new Thread(Listenning_ZX);
threadSever_ZX.IsBackground = true;
threadSever_ZX.Start();
return true;
}
catch (Exception)
{
return false;
//toolStripLabel1.Text = "开启错误,请检查IP和端口号!";
}
}
/// <summary>
/// 监听函数
/// </summary>
private void Listenning_ZX()
{
while (IsTcpStart_ZX)
{
try
{
Socket linsSocket = socketSever_ZX.Accept(); //;
if (ConnectCount_ZX < 1) //这里做个判断 单设备连接
{
ConnectCount_ZX++;
ClenctSocket_ZX = linsSocket;
string client = ClenctSocket_ZX.RemoteEndPoint.ToString();
//获取当前
this.Invoke(new Action(() =>
{
toolStripLabel1.Text = "当前有设备连接:" + client;
Set_Textbox_tile_ZX("当前有设备连接:" + client + " ", Color.Gray);
}));
Thread thr = new Thread(RecieveMsg_ZX);
ThreadList_ZX.Add(thr);
thr.IsBackground = true;
thr.Start(ClenctSocket_ZX);
}
else
{
linsSocket.Close();
}
}
catch (Exception)
{
throw;
}
}
}
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;
}
3. 服务端接受函数
/// <summary>
/// 接收函数
/// </summary>
/// <param name="socketClient"></param>
private void RecieveMsg_ZX(object socketClient)
{
byte[] arrMsgRec = new byte[1024 * 2];
StringBuilder builder = new StringBuilder();
StringBuilder TestBuilder = new StringBuilder();
Socket scketClient = socketClient as Socket;
while (IsTcpStart_ZX)
{
int length = -1;
try
{
if (scketClient.Poll(-1, SelectMode.SelectRead)) //判断socket是否掉线
{
int nRead = scketClient.Receive(arrMsgRec, SocketFlags.Peek);
if (nRead == 0)
{
this.Invoke(new Action(() =>
{
Set_Textbox_tile_ZX("客服端:" + scketClient.RemoteEndPoint.ToString() + "断开连接 ", Color.Gray);
}));
ClenctSocket_ZX = null;
ConnectCount_ZX = 0;
return;
}
length = scketClient.Receive(arrMsgRec);
}
}
catch (Exception)
{
}
以上就是基本的程序,上面我大概写下,网上教程很多参考下就行了
主要我讲讲这个这个TCP 作为主机 从机掉线这一块
-------首先说说 下面这个方法,如下图所示下面是他的方法说明,这是一个关于Socket的一个状态轮询的函数 这里我们轮询的是接受状态 SelectMode.SelectRead ,就是如下图所说如果 返回结果为 false 则连接处于 已关闭、重置、或者终止状态,前面的参数是等待响应,这里我们就直接触发就行。这个方法能有效检测链路层断线等情况
if (scketClient.Poll(-1, SelectMode.SelectRead)) //判断socket是否掉线
还有就是下面这个方法:
socketSever.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 1000, 1000), null);
官方API说明 =================》
网友参考资料1
大家可以参考下! 反正意思基本就发布包 保证连接双方通信正常,不正常时做处理。