using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.Threading; using System.Net; using SimpleServer; namespace SimpleServer { public class Server : IDisposable { #region DataMember private TcpListener listener; private Client currentClient; private object listenerLock = new object();//锁TcpListener;在BeginAcceptClient,EndAcceptClient,ServerClose这3函数使用;ServerClose之后不能再调用BeginAcceptClient,EndAcceptClient private bool serverStart = false; private EventWaitHandle eventWaitHdl = new EventWaitHandle(false, EventResetMode.ManualReset); //在事务处理结束后才触发下列事件 public event DlgNoParam ServerStartEvent; public event DlgNoParam ServerCloseEvent; public event DlgOneParam NewClientEvent; public event DlgOneParam RecvMsgEvent; public event DlgNoParam LocalDisconnectEvent; public event DlgOneParam RemoteDisconnectEvent; #endregion #region 服务器监听启动关闭和连接接收 public bool Start(string ip, int port) { bool result = false; try { if (!string.IsNullOrEmpty(ip) && port > 1024) { IPAddress ipAddr = IPAddress.Parse(ip); IPEndPoint point = new IPEndPoint(ipAddr, port); listener = new TcpListener(point); listener.Start(); result = true; serverStart = true; if (ServerStartEvent != null) { ServerStartEvent(); } } } catch { throw; } return result; } /// /// 有互斥资源 /// 接收连接主入口,监听启动后调用和每次接收到连接后调用 /// public void BeginAcceptClient() { try { while (true) { eventWaitHdl.Reset(); lock (listenerLock) { if (serverStart) { listener.BeginAcceptTcpClient(EndAcceptClient, null); } else { return; } } eventWaitHdl.WaitOne(); } } catch { throw; } } /// /// 有互斥资源 /// 接收到客户端连接时调用到,关闭listener时也调用到 /// /// private void EndAcceptClient(IAsyncResult ar) { try { TcpClient tcpclient = null; lock (listenerLock) { if (serverStart) { tcpclient = listener.EndAcceptTcpClient(ar);//在这句话之前或者client.BeginRead之前断掉远程客户端都没事,tcpclient都不为null } } eventWaitHdl.Set(); if (tcpclient != null)//listener.stop后tcpclient == null,不会进入下面代码 { InitClient(tcpclient); } } catch { //throw; } } /// /// 有互斥资源 /// 在listener监听状态下关闭listener时调用,资源释放时调用 /// /// public bool ServerClose() { bool result = false; try { lock (listenerLock) { if (serverStart) { serverStart = false; listener.Stop(); result = true; if (ServerCloseEvent != null) { ServerCloseEvent(); } } } } catch { throw; } return result; } #endregion #region Client相关操作 private void InitClient(TcpClient tcpclient) { currentClient = new Client(tcpclient); ClientDlgSubscribe(true); currentClient.BeginRead();//即使在这之前服务器断开,该函数返回值也等于1 } /// /// InitClient,CurrentClient_LocalDisconnectEvent,Client_DisconnectEvent调用到 /// 在事务处理结束后调用到 /// /// public void ClientDlgSubscribe(bool add) { if (add) { currentClient.NewClientEvent += new DlgOneParam(Client_NewClientEvent); currentClient.RecvMsgEvent += new DlgOneParam(Client_RecvMsgEvent); currentClient.RemoteDisconnectEvent += new DlgOneParam(Client_DisconnectEvent); currentClient.LocalDisconnectEvent += new DlgNoParam(CurrentClient_LocalDisconnectEvent); } else { currentClient.NewClientEvent -= new DlgOneParam(Client_NewClientEvent); currentClient.RecvMsgEvent -= new DlgOneParam(Client_RecvMsgEvent); currentClient.RemoteDisconnectEvent -= new DlgOneParam(Client_DisconnectEvent); currentClient.LocalDisconnectEvent -= new DlgNoParam(CurrentClient_LocalDisconnectEvent); } } public bool SendMsg(byte[] msg) { bool result = false; try { if (currentClient.SendMsg(msg)) { result = true; } } catch { throw; } return result; } /// /// 客户端连接情况下断开连接时调用,释放资源时调用 /// /// public bool DisconnectClient() { bool result = false; try { if (currentClient != null) { currentClient.Dispose(); result = true; } } catch { throw; } return result; } public void Client_NewClientEvent(string param) { if (NewClientEvent != null) { NewClientEvent(param); } } public void Client_RecvMsgEvent(byte[] param) { if (RecvMsgEvent != null) { RecvMsgEvent(param); } } public void Client_DisconnectEvent(string param) { ClientDlgSubscribe(false); if (RemoteDisconnectEvent != null) { RemoteDisconnectEvent(param); } } public void CurrentClient_LocalDisconnectEvent() { ClientDlgSubscribe(false); if (LocalDisconnectEvent != null) { LocalDisconnectEvent(); } } #endregion #region 资源释放 public void Dispose() { ServerClose(); DisconnectClient(); } #endregion } }