Common.TcpLibTcpServerS

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

    }

}

posted @ 2007-11-01 21:50  我想去长安  阅读(236)  评论(0编辑  收藏  举报