using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Threading;
|
|
namespace Bro.Common.Link
|
{
|
// 客户端动作代理
|
public delegate void OnClientOpen(TcpClient client);
|
public delegate void OnClientClose(TcpClient client);
|
public delegate void OnClientRecv(TcpClient client);
|
|
/// <summary>
|
/// TCP服务器
|
/// </summary>
|
public class TCPSvr
|
{
|
private static object synObj = new object();
|
public OnClientOpen ClientOpen;
|
public OnClientClose ClientClose;
|
public OnClientRecv ClientRecv;
|
|
// 服务器描述
|
public string Desp {get;set;}
|
// 服务器IP
|
public string ServerIP { get;set; }
|
// 服务器端口
|
public int ServerPort { get; set; }
|
// 服务器监听
|
private TcpListener tcpSvr = null;
|
// 停止标示
|
private bool bStop = false;
|
// 监听线程
|
private Thread listenThread;
|
private Thread pollThread;
|
|
private Dictionary<Socket,TcpClient> clientsMap = new Dictionary<Socket,TcpClient>();
|
|
public TCPSvr()
|
{
|
}
|
|
public TCPSvr(string ip, int port)
|
{
|
ServerIP = ip;
|
ServerPort = port;
|
}
|
|
/// <summary>
|
/// 初始化
|
/// </summary>
|
/// <returns></returns>
|
public bool Init()
|
{
|
try
|
{
|
var ip = IPAddress.Parse(ServerIP);
|
|
tcpSvr = new TcpListener(ip, ServerPort);
|
|
bStop = false;
|
}
|
catch(Exception ex)
|
{
|
Trace.TraceError("TCP server init fail,ex:{0}", ex);
|
return false;
|
}
|
|
return true;
|
}
|
|
/// <summary>
|
/// 启动监听
|
/// </summary>
|
/// <returns></returns>
|
public bool Start()
|
{
|
try
|
{
|
clientsMap.Clear();
|
|
tcpSvr.Start();
|
|
listenThread = new Thread(new ThreadStart(DoAcceptCallBack));
|
listenThread.Start();
|
|
pollThread = new Thread(new ThreadStart(PollThread));
|
pollThread.Start();
|
|
bStop = false;
|
}
|
catch(Exception ex)
|
{
|
Trace.TraceError("TCP server start listen fail,ex:{0}", ex);
|
return false;
|
}
|
|
return true;
|
}
|
|
/// <summary>
|
/// 停止监听
|
/// </summary>
|
public void Stop()
|
{
|
bStop = true;
|
|
try
|
{
|
tcpSvr.Stop();
|
|
listenThread.Join();
|
pollThread.Join();
|
|
}
|
catch(Exception ex)
|
{
|
Trace.TraceError("TCP server stop listen fail,ex:{0}", ex);
|
}
|
|
bStop = true;
|
}
|
|
/// <summary>
|
/// 关闭客户端
|
/// </summary>
|
/// <param name="client"></param>
|
public void Close(TcpClient client)
|
{
|
lock(synObj)
|
{
|
clientsMap.Remove(client.Client);
|
|
client.Close();
|
}
|
}
|
|
/// <summary>
|
/// 移除客户端监听
|
/// </summary>
|
/// <param name="client"></param>
|
public void Remove(TcpClient client)
|
{
|
lock (synObj)
|
{
|
clientsMap.Remove(client.Client);
|
}
|
}
|
|
/// <summary>
|
/// 监听线程
|
/// </summary>
|
private void PollThread()
|
{
|
for(;;)
|
{
|
if (bStop)
|
{
|
CloseAllClient();
|
|
Trace.TraceInformation("{0} tcp server stop trigger", Desp);
|
break;
|
}
|
|
lock(synObj)
|
{
|
PollRecv();
|
}
|
|
}
|
|
Trace.TraceInformation("{0} tcp server stop finish", Desp);
|
}
|
|
/// <summary>
|
/// 新接入客户端连接
|
/// </summary>
|
/// <param name="ar"></param>
|
private void DoAcceptCallBack()
|
{
|
for (; ; )
|
{
|
TcpClient client = null;
|
|
try
|
{
|
if (!tcpSvr.Pending())
|
{
|
Thread.Sleep(100);
|
continue;
|
}
|
|
|
client = tcpSvr.AcceptTcpClient();
|
|
// 接收发送缓存大小
|
client.ReceiveBufferSize = 2048;
|
client.SendBufferSize = 2048;
|
|
// 读写超时
|
client.SendTimeout = 2000;
|
client.ReceiveTimeout = 200;
|
|
lock (synObj)
|
{
|
clientsMap.Add(client.Client, client);
|
|
// 通知客户端连接进入
|
if (null != ClientOpen)
|
{
|
Trace.TraceInformation("DoAcceptCallBack {0} tcp server, accept client{1}", Desp, client.Client.RemoteEndPoint);
|
|
ClientOpen(client);
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
client?.Close();
|
Trace.TraceInformation("DoAcceptCallBack fail, ex:{0},{1} tcp server, accept client{2}", ex.Message,
|
Desp, client?.Client.RemoteEndPoint.ToString());
|
return;
|
}
|
}
|
}
|
|
/// <summary>
|
/// 检查数据接收
|
/// </summary>
|
private void PollRecv()
|
{
|
var rList = new ArrayList();
|
var eList = new ArrayList();
|
|
foreach(var item in clientsMap)
|
{
|
var socket = item.Key;
|
|
rList.Add(socket);
|
eList.Add(socket);
|
}
|
|
if (clientsMap.Count == 0)
|
{
|
Thread.Sleep(200);
|
return;
|
}
|
|
try
|
{
|
Thread.Sleep(200);
|
Socket.Select(rList, null, eList, 200);
|
|
// 客户端异常则关闭
|
foreach(var item in eList)
|
{
|
Socket socket = (Socket)item;
|
TcpClient client;
|
|
if ( clientsMap.TryGetValue(socket, out client) && null != ClientClose )
|
{
|
client.Close();
|
|
ClientClose(client);
|
}
|
|
clientsMap.Remove(socket);
|
}
|
|
// 客户端是否有数据
|
foreach(var item in rList)
|
{
|
Socket socket = (Socket)item;
|
TcpClient client;
|
|
if ( clientsMap.TryGetValue(socket, out client) && null != ClientRecv )
|
{
|
ClientRecv(client);
|
|
}
|
}
|
}
|
catch(Exception ex)
|
{
|
Trace.TraceInformation("CloseAllClient except{0}, {1} tcp server", ex.Message, Desp);
|
}
|
}
|
|
/// <summary>
|
/// 关闭所有客户端连接
|
/// </summary>
|
private void CloseAllClient()
|
{
|
Trace.TraceInformation("CloseAllClient {0} tcp server, client cnt{0}", Desp, clientsMap.Count);
|
|
foreach(var item in clientsMap)
|
{
|
var client = item.Value;
|
try
|
{
|
client.Close();
|
|
if ( null != ClientClose )
|
{
|
ClientClose(client);
|
}
|
}
|
catch(Exception ex)
|
{
|
Trace.TraceInformation("CloseAllClient except{0}, {1} tcp server, accept client{2}", ex.Message, Desp, client.Client.RemoteEndPoint);
|
}
|
|
}
|
|
clientsMap.Clear();
|
}
|
}
|
}
|