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);
///
/// TCP服务器
///
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 clientsMap = new Dictionary();
public TCPSvr()
{
}
public TCPSvr(string ip, int port)
{
ServerIP = ip;
ServerPort = port;
}
///
/// 初始化
///
///
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;
}
///
/// 启动监听
///
///
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;
}
///
/// 停止监听
///
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;
}
///
/// 关闭客户端
///
///
public void Close(TcpClient client)
{
lock(synObj)
{
clientsMap.Remove(client.Client);
client.Close();
}
}
///
/// 移除客户端监听
///
///
public void Remove(TcpClient client)
{
lock (synObj)
{
clientsMap.Remove(client.Client);
}
}
///
/// 监听线程
///
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);
}
///
/// 新接入客户端连接
///
///
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;
}
}
}
///
/// 检查数据接收
///
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);
}
}
///
/// 关闭所有客户端连接
///
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();
}
}
}