• Common.TcpLibTcpServerWIOCP


    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>
    /// WIOCP Socket处理服务器端
    /// </summary>
        public class TcpServerWIOCP : Common.TcpLib.ITcpServer
        {
            private Socket _listener;
            private string _listenerIp = "127.0.0.1";
            private int _port;
            private int _backlog = 100;
            private int _bufferSize = 1024;
            private Thread _thread = null;
            private bool _disposed;
            private bool _debug = false;
            private ManualResetEvent allDone = new ManualResetEvent(false);
            private ManualResetEvent sendDone = new ManualResetEvent(false);
            private object _stopLock = new object();
            private bool _sotpMessage = false;

            private List<Socket> _cs = new List<Socket>();

            #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 TcpServerWIOCP(int port)
            {
                _port = port;
            }

            public TcpServerWIOCP(int port, int backlog)
            {
                _port = port;
                _backlog = backlog;
            }

            public TcpServerWIOCP(int port, int backlog, int buffterSize)
            {
                _port = port;
                _backlog = backlog;
                _bufferSize = buffterSize;
            }

            public TcpServerWIOCP(string listenerIp, int port)
            {
                _listenerIp = listenerIp;
                _port = port;
            }

            public TcpServerWIOCP(string listenerIp, int port, int backlog)
            {
                _listenerIp = listenerIp;
                _port = port;
                _backlog = backlog;
            }

            public TcpServerWIOCP(string listenerIp, int port, int backlog, int buffterSize)
            {
                _listenerIp = listenerIp;
                _port = port;
                _backlog = backlog;
                _bufferSize = buffterSize;
            }

            ~TcpServerWIOCP()
            {
                if (!_disposed)
                {
                    Stop();
                }
            }
            #endregion

            #region Private Methods

            private void Dispose()
            {
                if (!_disposed)
                {
                    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 StartListening(object obj)
            {
                try
                {
                    bool optionValue = (bool)obj;
                    _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);

                    _sotpMessage = false;
                    _stopLock = new object();
                    while (true)
                    {
                        if (_listener == null)
                        {
                            lock (_stopLock)
                            {
                                if (!_sotpMessage)
                                {
                                    OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
                                    _sotpMessage = true;
                                }
                            }
                            return;
                        }
                        allDone.Reset();
                        _listener.BeginAccept(new AsyncCallback(AcceptCallback), _listener);
                        allDone.WaitOne();
                    }

                }
                catch (Exception ex)
                {
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "Start Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
            }

            private void AcceptCallback(IAsyncResult ar)
            {
                Socket handler = null;
                _Bgz_ConnectionState stx = new _Bgz_ConnectionState();
                try
                {
                    Socket listener = ar.AsyncState as Socket;
                    if (_listener == null)
                    {
                        lock (_stopLock)
                        {
                            if (!_sotpMessage)
                            {
                                OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
                                _sotpMessage = true;
                            }
                        }
                        return;
                    }
                    handler = listener.EndAccept(ar);
                    _cs.Add(handler);
                    stx._conn = handler;
                    OnAcceptEvent(stx);
                   
                    #region 处理Socket网络异常断开
                    uint dummy = 0;
                    byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
                    BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
                    BitConverter.GetBytes((uint)50000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
                    BitConverter.GetBytes((uint)50000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
                    _listener.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
                    #endregion

                    handler.BeginReceive(stx._buffer, 0, 0, 0, new AsyncCallback(ReadCallBack), handler);
                }
                catch (Exception ex)
                {
                    DropConnection(stx);
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "AcceptCallback Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
                finally
                {
                    allDone.Set();
                }
            }

            private void DropConnection(_Bgz_ConnectionState stx)
            {
                try
                {
                    lock (this)
                    {
                        if (_listener == null)
                        {
                            lock (_stopLock)
                            {
                                if (!_sotpMessage)
                                {
                                    OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
                                    _sotpMessage = true;
                                }
                            }
                            return;
                        }
                        OnDropConnectEvent(stx);
                        if (_cs.Contains(stx._conn))
                            _cs.Remove(stx._conn);

                        if (stx._conn != null)
                        {
                            IPEndPoint info = (IPEndPoint)stx._conn.RemoteEndPoint;
                            string str = info.Address.ToString() + ":" + info.Port.ToString();
                            OnErrorEvent(ErrorType.DisAccept, "关闭了远程连接[" + str + "]!", 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", null);
                    }
                }
            }

            private void ReadCallBack(IAsyncResult ar)
            {
                Socket handler = null;
                try
                {

                    handler = (Socket)ar.AsyncState;
                    _Bgz_ConnectionState stx = new _Bgz_ConnectionState(handler);

                     if (this._listener == null)
                    {
                        lock (_stopLock)
                        {
                            if (!_sotpMessage)
                            {
                                OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
                                _sotpMessage = true;
                            }
                        }
                        return;
                    }

                    if (handler == null) return;

                    handler.EndReceive(ar);


                    if (handler.Available == 0)
                    {
                        DropConnection(stx);
                        return;
                    }

                    try
                    {
                        lock (this)
                        {
                            OnReceiveBeginEvent(stx);

                            #region receive

                            stx._buffer = new byte[0];
                            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 > _bufferSize)
                                        stx._buffer = new byte[_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);
                                    }
                                }
                            }
                            #endregion

                            OnReceiveEndEvent(stx);
                        }
                    }
                    catch (Exception ex)
                    {
                        DropConnection(stx);
                        if (Debug)
                        {
                            OnErrorEvent(ErrorType.Catch, "ReadCallBack.1 Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", stx);
                        }
                    }

                    if (handler == null) return;
                    if (handler.Connected)
                        handler.BeginReceive(stx._buffer, 0, 0, 0, new AsyncCallback(ReadCallBack), handler);
                }
                catch (Exception ex)
                {
                    if (this._listener == null)
                    {
                        lock (_stopLock)
                        {
                            if (!_sotpMessage)
                            {
                                OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
                                _sotpMessage = true;
                            }
                        }
                        return;
                    }

                    if (handler != null)
                    {
                        _Bgz_ConnectionState stx = new _Bgz_ConnectionState(handler);
                        DropConnection(stx);
                    }
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "ReadCallBack.2 Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
            }

            private void SendCallback(IAsyncResult ar)
            {
                try
                {
                    Socket client = (Socket)ar.AsyncState;
                    int bytesSent = client.EndSend(ar);
                }
                catch (Exception ex)
                {
                    OnErrorEvent(ErrorType.Catch, "出错信息提示:\r\n" + ex.Message, null);
                }
                finally
                {
                    sendDone.Set();
                }
            }

            #endregion

            #region Public Methods
            public void Start()
            {
                Start(false);
            }

            public void Start(bool optionValue)
            {
                _thread = new Thread(new ParameterizedThreadStart(StartListening));
                _thread.Name = "TcpServerIOCP.Listening";
                _thread.Start(optionValue);
            }

            public void Send(byte[] msg)
            {
                try
                {
                    foreach (Socket s in ClientSockets)
                    {
                        Send(s, msg);
                    }
                }
                catch (Exception ex)
                {
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "Send Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
            }

            public void Send(Socket ClientSocket, byte[] msg)
            {
                try
                {
                    if (ClientSocket != null)
                    {
                        if (ClientSocket.Connected)
                            ClientSocket.Send(msg);
                        else
                        {
                            IPEndPoint info = (IPEndPoint)ClientSocket.RemoteEndPoint;
                            string str = info.Address.ToString() + ":" + info.Port.ToString();
                            OnErrorEvent(ErrorType.DisConnect, "客户端[" + str + "]的连接未建立,不能发送信息!", null);
                            ClientSocket.Close();
                        }
                    }
                    else
                    {
                        OnErrorEvent(ErrorType.DisAccept, "客户端的连接未建立,不能发送信息!", null);
                    }
                }
                catch (Exception ex)
                {
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "Send Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
            }

            public void SendAsync(Socket ClientSocket , byte[] msg)
            {
                try
                {
                    if (ClientSocket.Connected == false)
                    {
                        throw (new Exception("没有连接客户端不可以发送信息!"));
                    }

                    byte[] buffer;
                    int count = msg.Length;
                    int cur = 0;
                    while (count > 0)
                    {
                        if (count > this._bufferSize)
                            buffer = new byte[this._bufferSize];
                        else
                            buffer = new byte[count];

                        for (int i = 0; i < buffer.Length; i++)
                        {
                            buffer[i] = msg[cur + i];
                        }
                        count -= buffer.Length;

                        cur += buffer.Length;

                        ClientSocket.BeginSend(buffer, 0, buffer.Length, 0, new AsyncCallback(SendCallback), ClientSocket);
                        sendDone.WaitOne();
                    }
                }
                catch (Exception ex)
                {
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "Send Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
            }

            public void SendAsync(Socket ClientSocket, Stream Astream)
            {
                try
                {
                    if (ClientSocket.Connected == false)
                    {
                        throw (new Exception("没有连接客户端不可以发送信息!"));
                    }
                   
                    byte[] buffer ;
                    long count = Astream.Length;
                    while (count > 0)
                    {
                        if (count > this._bufferSize)
                            buffer = new byte[this._bufferSize];
                        else
                            buffer = new byte[count];

                        Astream.Read(buffer, 0, buffer.Length);
                        count -= buffer.Length;
                        ClientSocket.BeginSend(buffer, 0, buffer.Length, 0, new AsyncCallback(SendCallback), ClientSocket);
                        sendDone.WaitOne();
                    }
                }
                catch (Exception ex)
                {
                    if (Debug)
                    {
                        OnErrorEvent(ErrorType.Catch, "Send Error![Message]:\r\n" + ex.Message + "[StackTrace]:\r\n" + ex.StackTrace + "\r\n", null);
                    }
                }
            }

            public void Stop()
            {
                try
                {
                    if (_listener == null)
                    {
                        lock (_stopLock)
                        {
                            if (!_sotpMessage)
                            {
                                OnErrorEvent(ErrorType.DisAccept, "服务器关闭了监听!", null);
                                _sotpMessage = true;
                            }
                        }
                        return;
                    }
                    if (_thread != null)
                    {
                        foreach (Socket s in _cs)
                        {
                            if (s != null)
                                if (s.Connected)
                                {

                                    IPEndPoint info = (IPEndPoint)s.RemoteEndPoint;
                                    string str = info.Address.ToString() + ":" + info.Port.ToString();
                                    OnErrorEvent(ErrorType.DisAccept, "关闭了远程连接[" + str + "]!", null);
                                    s.Close();
                                }
                        }

                        _cs.Clear();
                        _listener.Close();
                        _listener = null;
                        _thread.Join();
                        _thread = null;
                    }
                }
                catch (Exception ex)
                {
                    OnErrorEvent(ErrorType.Catch, "出错信息提示:\r\n" + ex.Message, null);
                }
            }

            #endregion

            #region Property
            /// <summary>
            /// 获取挂起连接队列的最大长度
            /// </summary>
            public int BackLog
            {
                get
                {
                    return _backlog;
                }
            }

            public int BufferSize
            {
                get
                {
                    return _bufferSize;
                }
            }

            public Socket[] ClientSockets
            {
                get
                {
                    Socket[] sockets = new Socket[this._cs.Count];
                    _cs.CopyTo(sockets);
                    return sockets;
                }
            }

            public bool Debug
            {
                get
                {
                    return _debug;
                }
                set
                {
                    _debug = value;
                }
            }
            #endregion
        }
    }

  • 相关阅读:
    ThingJS,轻松切换3D场景!
    ThingJS,以可视化的方式解决管线难题
    可视化能成为物联网“最后一公里”么?
    ThingJS 新手教程之初识在线开发(一)
    threejs和ThingJS的区别,ThingJS收费么?
    带你了解为什么许多公司都会选择使用ThingJS制作Demo进行投标!
    物联网可视化平台有哪些?ThingJS怎么样?
    ThingJS园区搭建工具模模搭介绍
    ThingJS,物联网可视化方面的专家平台!
    ajax的post的方法,不报错,就是不输出信息
  • 原文地址:https://www.cnblogs.com/bigmouthz/p/946773.html
Copyright © 2020-2023  润新知