在网上找的记一下

public abstract class Server {
    static readonly ILog logger = LogManager.GetLogger(typeof(Server));
 
    public int Port { getset; }
    public event ClientEventHandler OnClientAcceptEvent;
    public event ClientEventHandler OnClientOnlineEvent;
    public event ClientEventHandler OnClientRemoveEvent;
    private bool bStarted;
    static private int NextClientId = 0;
    private TcpListener _listener;
    protected Dictionary<int, Client> id2client = new Dictionary<int, Client>();
    private List<Client> noHeartBeatClients = new List<Client>();
 
    public bool HasHeartBeat;
    private int CheckHeartBeatInterval = 30 * 1000;// ms
    protected System.Timers.Timer CheckHeartBeatTimer = new System.Timers.Timer();
    private object id2clientCS = new object();
    private object noHeartBeatClientsCS = new object();
 
    private Server() {
        CheckHeartBeatTimer.Elapsed += (o1, a1) => {
            if(HasHeartBeat == falsereturn;
            List<Client> kickClientList = new List<Client>();
            lock(id2clientCS) {
                try {
                    DateTime now = DateTime.Now;
                    foreach(KeyValuePair<int, Client> pair in id2client) {
                        try {
                            Client client = pair.Value;
                            TimeSpan offset = now - client.LastHeartBeat;
                            if(client != null && client.State == Client.ConnectionState.Connected && offset.TotalMilliseconds > CheckHeartBeatInterval) {
                                kickClientList.Add(pair.Value);
                                logger.InfoFormat("检测到心跳超时: [IP]{0}, [ID]{1}, [Time]{2}", client.ClientIpAddress, pair.Key, DateTime.Now.ToString());
                            }
                        catch { }
                    }
                catch(Exception ex) {
                    logger.WarnFormat("心跳检测时发生异常: \n{0}", ex);
                }
            }
            kickClientList.ForEach(p => p.Close());
            lock(noHeartBeatClientsCS) {
                kickClientList.ForEach(c => noHeartBeatClients.RemoveAll(p => p.Id == c.Id));
            }
        };
    }
 
    public Server(int port)
        this() {
        this.Port = port;
    }
 
    public List<Client> Clients {
        get {
            List<Client> result = new List<Client>();
            lock(id2clientCS) {
                foreach(Client each in id2client.Values) {
                    result.Add(each);
                }
            }
            return result;
        }
    }
 
    public virtual void Open() {
        _listener = new TcpListener(Port);
        logger.InfoFormat("Server#Open port={0}", Port);
        try {
            _listener.Start();
            if(HasHeartBeat) {
                CheckHeartBeatTimer.Stop();
                CheckHeartBeatTimer.Interval = CheckHeartBeatInterval;
                CheckHeartBeatTimer.Start();
            }
            _listener.BeginAcceptTcpClient(new AsyncCallback(OnAccept), null);
            bStarted = true;
        catch(SocketException ex) {
            logger.WarnFormat("服务器监听发生异常:{0}\nSocket ErrorCode: {1}\n提示:请检查端口是否已被占用", ex.Message, ex.ErrorCode);
            throw ex;
        catch(Exception ex) {
            logger.Warn(ex);
            throw ex;
        }
    }
 
    public virtual void Close() {
        try {
            if(HasHeartBeat) {
                CheckHeartBeatTimer.Stop();
            }
            _listener.Stop();
            bStarted = false;
 
            lock(id2clientCS) {
                foreach(Client each in id2client.Values) {
                    try if(each != null)each.Close(); } catch { }
                }
                id2client.Clear();
            }
        catch(Exception ex) {
            logger.Warn(ex);
            throw ex;
        }
    }
 
    private void OnAccept(IAsyncResult ar) {
        try {
            Client client = CreateClient(NextClientId++, _listener.EndAcceptTcpClient(ar), this);
            client.LastHeartBeat = DateTime.Now;
            client.PostOfflineEvent += (obj, args) => RemoveClient(client);
            lock(id2clientCS) {
                id2client.Add(client.Id, client);
            }
            lock(noHeartBeatClientsCS) {
                noHeartBeatClients.Add(client);
            }
            if(OnClientAcceptEvent != null) OnClientAcceptEvent(client);
        catch(ObjectDisposedException) { } catch(Exception ex) {
            logger.Warn(ex);
        finally {
            try {
                _listener.BeginAcceptTcpClient(new AsyncCallback(OnAccept), null);
            catch(Exception) {
                // ignore
            }
        }
    }
 
    protected abstract Client CreateClient(int id, TcpClient tcpClient, Server server);
 
    public void RemoveClient(Client client) {
        if(bStarted == falsereturn;
        lock(id2clientCS) {
            id2client.Remove(client.Id);
        }
        if(OnClientRemoveEvent != null) OnClientRemoveEvent(client);
    }
 
    public void GetHeartBeat(Client client) {
        if(HasHeartBeat == falsereturn;
 
        client.LastHeartBeat = DateTime.Now;
        lock(noHeartBeatClientsCS) {
            int index = noHeartBeatClients.FindIndex(p => p.Id == client.Id);
            if(index == -1) return;
            try {
                if(OnClientOnlineEvent != null) OnClientOnlineEvent(client);
            catch(Exception ex) {
                logger.Warn(ex);
            }
            noHeartBeatClients.RemoveAt(index);
        }
    }
}
 
http://www.doc88.com/p-4714417112965.html
posted @ 2017-08-22 16:00  爱上未来的你  阅读(143)  评论(0编辑  收藏  举报