266 lines
7.9 KiB
C#
266 lines
7.9 KiB
C#
|
|
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_10 : 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<string> NewClientEvent;
|
|||
|
|
public event DlgOneParam<byte[]> RecvMsgEvent;
|
|||
|
|
public event DlgNoParam LocalDisconnectEvent;
|
|||
|
|
public event DlgOneParam<string> 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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 有互斥资源
|
|||
|
|
/// 接收连接主入口,监听启动后调用和每次接收到连接后调用
|
|||
|
|
/// </summary>
|
|||
|
|
public void BeginAcceptClient()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
eventWaitHdl.Reset();
|
|||
|
|
lock (listenerLock)
|
|||
|
|
{
|
|||
|
|
if (serverStart)
|
|||
|
|
{
|
|||
|
|
listener.BeginAcceptTcpClient(EndAcceptClient, null);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
eventWaitHdl.WaitOne();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
throw;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 有互斥资源
|
|||
|
|
/// 接收到客户端连接时调用到,关闭listener时也调用到
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="ar"></param>
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 有互斥资源
|
|||
|
|
/// 在listener监听状态下关闭listener时调用,资源释放时调用
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
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
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// InitClient,CurrentClient_LocalDisconnectEvent,Client_DisconnectEvent调用到
|
|||
|
|
/// 在事务处理结束后调用到
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="add"></param>
|
|||
|
|
public void ClientDlgSubscribe(bool add)
|
|||
|
|
{
|
|||
|
|
if (add)
|
|||
|
|
{
|
|||
|
|
currentClient.NewClientEvent += new DlgOneParam<string>(Client_NewClientEvent);
|
|||
|
|
currentClient.RecvMsgEvent += new DlgOneParam<byte[]>(Client_RecvMsgEvent);
|
|||
|
|
currentClient.RemoteDisconnectEvent += new DlgOneParam<string>(Client_DisconnectEvent);
|
|||
|
|
currentClient.LocalDisconnectEvent += new DlgNoParam(CurrentClient_LocalDisconnectEvent);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
currentClient.NewClientEvent -= new DlgOneParam<string>(Client_NewClientEvent);
|
|||
|
|
currentClient.RecvMsgEvent -= new DlgOneParam<byte[]>(Client_RecvMsgEvent);
|
|||
|
|
currentClient.RemoteDisconnectEvent -= new DlgOneParam<string>(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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 客户端连接情况下断开连接时调用,释放资源时调用
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
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
|
|||
|
|
}
|
|||
|
|
}
|