using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
namespace Common.TcpLib
{
/// <summary>
/// 同步Socket处理服务器端(专用于短连接)
/// </summary>
public class TcpServerS
{
private Socket _listener;
private string _listenerIp = "127.0.0.1";
private int _port;
private int _backlog = 100;
private int _bufferSize = 1024;
private int _maxConnections = 100;
private Thread _accept;
private int _receiveTimeout = 100000;
private bool _disposed;
private bool _debug = false;
private object _stopLock = new object();
private bool _sotpMessage = false;
#region define delegates
/// <summary>
/// 服务器绑定后处理事件
/// </summary>
public _Bgz_OnBindEventDelegate FOnBindEventDelegate;
/// <summary>
/// Accept后处理事件
/// </summary>
public _Bgz_OnAcceptEventDelegate FOnAcceptEventDelegate;
/// <summary>
/// 接收到客户端数据后处理事件
/// </summary>
public _Bgz_OnReceiveBeginEventDelegate FOnReceiveBeginEventDelegate;
public _Bgz_OnReceiveingEventDelegate FOnReceiveingEventDelegate;
public _Bgz_OnReceiveEndEventDelegate FOnReceiveEndEventDelegate;
/// <summary>
/// 报错信息处理
/// </summary>
public _Bgz_OnErrorEventDelegate FOnErrorEventDelegate;
/// <summary>
/// 断掉与客户机的连接前处理事件
/// </summary>
public _Bgz_OnDropConnectEventDelegate FOnDropConnectEventDelegate;
#endregion
#region Event
private void OnBindEvent(_Bgz_ConnectionState state)
{
if (FOnBindEventDelegate != null) FOnBindEventDelegate(state);
}
private void OnAcceptEvent(_Bgz_ConnectionState state)
{
if (FOnAcceptEventDelegate != null) FOnAcceptEventDelegate(state);
}
private void OnReceiveBeginEvent(_Bgz_ConnectionState state)
{
if (FOnReceiveBeginEventDelegate != null) FOnReceiveBeginEventDelegate(state);
}
private void OnReceiveingEvent(_Bgz_ConnectionState state)
{
if (FOnReceiveingEventDelegate != null) FOnReceiveingEventDelegate(state);
}
private void OnReceiveEndEvent(_Bgz_ConnectionState state)
{
if (FOnReceiveEndEventDelegate != null) FOnReceiveEndEventDelegate(state);
}
private void OnErrorEvent(ErrorType errortype, string msg, _Bgz_ConnectionState state)
{
if (FOnErrorEventDelegate != null) FOnErrorEventDelegate(errortype, msg, state);
}
private void OnDropConnectEvent(_Bgz_ConnectionState state)
{
if (FOnDropConnectEventDelegate != null) FOnDropConnectEventDelegate(state);
}
#endregion
#region Constructor and Destructor
public TcpServerS(string listenerIp, int port)
{
_listenerIp = listenerIp;
_port = port;
}
public TcpServerS(string listenerIp, int port, int backlog)
{
_listenerIp = listenerIp;
_port = port;
_backlog = backlog;
}
public TcpServerS(string listenerIp, int port, int backlog, int bufferSize)
{
_listenerIp = listenerIp;
_port = port;
_backlog = backlog;
_bufferSize = bufferSize;
}
public TcpServerS(string listenerIp, int port, int backlog, int bufferSize, int maxConnections)
{
_listenerIp = listenerIp;
_port = port;
_backlog = backlog;
_bufferSize = bufferSize;
_maxConnections = maxConnections;
}
public TcpServerS(int port)
{
_port = port;
}
public TcpServerS(int port, int backlog)
{
_port = port;
_backlog = backlog;
}
public TcpServerS(int port, int backlog, int bufferSize)
{
_port = port;
_backlog = backlog;
_bufferSize = bufferSize;
}
public TcpServerS(int port, int backlog, int bufferSize, int maxConnections)
{
_port = port;
_backlog = backlog;
_bufferSize = bufferSize;
_maxConnections = maxConnections;
}
~TcpServerS()
{
if (!_disposed)
{
Stop();
}
}
#endregion
#region Private Methods
private void Dispose()
{
if (!_disposed)
{
if (_accept != null) Stop();
GC.Collect();
GC.WaitForPendingFinalizers();
this.FOnAcceptEventDelegate = null;
this.FOnBindEventDelegate = null;
this.FOnDropConnectEventDelegate = null;
this.FOnErrorEventDelegate = null;
this.FOnReceiveBeginEventDelegate = null;
this.FOnReceiveEndEventDelegate = null;
this.FOnReceiveingEventDelegate = null;
_disposed = true;
}
}
private void ClientWorkThread()
{
try
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
if (this._listener == null)
{
lock (_stopLock)
{
if (!_sotpMessage)
{
OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
_sotpMessage = true;
}
}
return;
}
Socket handler = _listener.Accept();
_Bgz_ConnectionState stx = new _Bgz_ConnectionState(handler);
OnAcceptEvent(stx);
try
{
#region read to bytes
stx._buffer = new byte[0];
stx._count = 0;
stx._getonceall = false;
if (handler == null) break;
handler.Receive(stx._buffer);
if (handler.Available == 0)
{
DropConnection(stx);
break;
}
OnReceiveBeginEvent(stx);
stx._count = 0;
stx._dataStream.SetLength(0);
stx._dataStream.Position = 0;
if (stx._getonceall)
{
stx._buffer = new byte[handler.Available];
int ret = handler.Receive(stx._buffer, 0, stx._buffer.Length, SocketFlags.None);
if (ret > 0)
{
stx._dataStream.Write(stx._buffer, 0, stx._buffer.Length);
stx._count++;
OnReceiveingEvent(stx);
}
}
else
{
while (handler.Available > 0)
{
if (handler.Available > this._bufferSize)
stx._buffer = new byte[this._bufferSize];
else
stx._buffer = new byte[handler.Available];
int ret = handler.Receive(stx._buffer, 0, stx._buffer.Length, SocketFlags.None);
if (ret > 0)
{
stx._dataStream.Write(stx._buffer, 0, stx._buffer.Length);
stx._count++;
OnReceiveingEvent(stx);
}
}
}
OnReceiveEndEvent(stx);
#endregion
}
catch (Exception ex)
{
DropConnection(stx);
if (Debug)
{
OnErrorEvent(ErrorType.Catch, "ReceiveThread.1 Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", stx);
}
break;
}
DropConnection(stx);
}
}
catch (Exception ex)
{
if (this._listener == null)
{
lock (_stopLock)
{
if (!_sotpMessage)
{
OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
_sotpMessage = true;
}
}
return;
}
if (Debug)
{
OnErrorEvent(ErrorType.Catch, "ReceiveThread.2 Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
}
}
}
private void DropConnection(_Bgz_ConnectionState stx)
{
try
{
lock (this)
{
OnDropConnectEvent(stx);
if (stx._conn != null)
if (stx._conn.Connected) stx._conn.Close();
}
}
catch (Exception ex)
{
if (Debug)
{
OnErrorEvent(ErrorType.Catch, "DropConnection Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", stx);
}
}
}
#endregion
#region Public Methods
public void Start()
{
Start(false);
}
public void Start(bool optionValue)
{
try
{
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
#region 处理Socket端口复用
_listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue);
#endregion
_listener.Bind(new IPEndPoint(IPAddress.Parse(_listenerIp), _port));
_listener.Listen(_backlog);
_Bgz_ConnectionState stx = new _Bgz_ConnectionState(_listener);
OnBindEvent(stx);
#region 处理Socket网络异常断开
uint dummy = 0;
byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
_listener.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
#endregion
#region 设置Socket接收延时的处理
stx._conn.ReceiveTimeout = _receiveTimeout;
#endregion
Thread[] clientThreadList = new Thread[_maxConnections];
for (int i =0; i < this._maxConnections; i++)
{
clientThreadList[i] = new Thread(new ThreadStart(ClientWorkThread));
clientThreadList[i].Start();
}
}
catch (Exception ex)
{
if (Debug)
{
OnErrorEvent(ErrorType.Catch, "Start Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
}
}
}
public void Stop()
{
try
{
lock (this)
{
if (_accept != null)
{
_listener.Close();
_listener = null;
_accept.Join();
_accept = null;
}
}
}
catch (Exception ex)
{
if (Debug)
{
OnErrorEvent(ErrorType.Catch, "Stop Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
}
}
}
public void Send(Socket ClientSocket, byte[] msg)
{
try
{
if (ClientSocket.Connected)
{
ClientSocket.Send(msg);
}
else
{
OnErrorEvent(ErrorType.DisConnect, "未与服务器建立链接,导致发送数据失败!", null);
}
}
catch (Exception ex)
{
if (Debug)
{
OnErrorEvent(ErrorType.Catch, "Send Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
}
}
}
#endregion
#region property
public int BackLog
{
get
{
return _backlog;
}
}
public int BufferSize
{
get
{
return _bufferSize;
}
}
public bool Debug
{
get
{
return _debug;
}
set
{
_debug = value;
}
}
#endregion
}
}