using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace HPSocketCS { public class UdpServer : UdpServer { public new T GetExtra(IntPtr connId) { return base.GetExtra(connId); } public bool SetExtra(IntPtr connId, T obj) { return base.SetExtra(connId, obj); } } public class UdpServer : ConnectionExtra, IServer { /// /// 连接到达事件 /// public event ServerEvent.OnAcceptEventHandler OnAccept; /// /// 数据包发送事件 /// public event ServerEvent.OnSendEventHandler OnSend; /// /// 准备监听了事件 /// public event ServerEvent.OnPrepareListenEventHandler OnPrepareListen; /// /// 数据到达事件 /// public event ServerEvent.OnReceiveEventHandler OnReceive; /// /// 数据到达事件(指针数据) /// public event ServerEvent.OnPointerDataReceiveEventHandler OnPointerDataReceive; /// /// 连接关闭事件 /// public event ServerEvent.OnCloseEventHandler OnClose; /// /// 服务器关闭事件 /// public event ServerEvent.OnShutdownEventHandler OnShutdown; /// /// 握手成功事件 /// public event ServerEvent.OnHandShakeEventHandler OnHandShake; protected IntPtr pServer = IntPtr.Zero; protected IntPtr pListener = IntPtr.Zero; /// /// 服务器ip /// public string IpAddress { get; set; } /// /// 服务器端口 /// public ushort Port { get; set; } protected bool IsCreate = false; public UdpServer() { CreateListener(); } ~UdpServer() { Destroy(); } /// /// 创建socket监听&服务组件 /// /// protected virtual bool CreateListener() { if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) { return false; } pListener = Sdk.Create_HP_UdpServerListener(); if (pListener == IntPtr.Zero) { return false; } pServer = Sdk.Create_HP_UdpServer(pListener); if (pServer == IntPtr.Zero) { return false; } IsCreate = true; return true; } /// /// 终止服务并释放资源 /// public virtual void Destroy() { Stop(); if (pServer != IntPtr.Zero) { Sdk.Destroy_HP_UdpServer(pServer); pServer = IntPtr.Zero; } if (pListener != IntPtr.Zero) { Sdk.Destroy_HP_UdpServerListener(pListener); pListener = IntPtr.Zero; } IsCreate = false; } /// /// 启动服务 /// /// public bool Start() { if (IsCreate == false) { return false; } if (pServer == IntPtr.Zero) { return false; } SetCallback(); return Sdk.HP_Server_Start(pServer, IpAddress, Port); } /// /// 停止服务 /// /// public bool Stop() { if (pServer == IntPtr.Zero) { return false; } return Sdk.HP_Server_Stop(pServer); } /// /// 发送数据 /// /// /// /// /// public bool Send(IntPtr connId, byte[] bytes, int size) { return Sdk.HP_Server_Send(pServer, connId, bytes, size); } /// /// 发送数据 /// /// /// /// /// public bool Send(IntPtr connId, IntPtr bufferPtr, int size) { return Sdk.HP_Server_Send(pServer, connId, bufferPtr, size); } /// /// 发送数据 /// /// /// /// 针对bytes的偏移 /// 发多大 /// public bool Send(IntPtr connId, byte[] bytes, int offset, int size) { return Sdk.HP_Server_SendPart(pServer, connId, bytes, size, offset); } /// /// 发送数据 /// /// /// /// 针对bufferPtr的偏移 /// 发多大 /// public bool Send(IntPtr connId, IntPtr bufferPtr, int offset, int size) { return Sdk.HP_Server_SendPart(pServer, connId, bufferPtr, size, offset); } /// /// 发送多组数据 /// 向指定连接发送多组数据 /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) /// /// 连接 ID /// 发送缓冲区数组 /// 发送缓冲区数目 /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 public bool SendPackets(IntPtr connId, WSABUF[] pBuffers, int count) { return Sdk.HP_Server_SendPackets(pServer, connId, pBuffers, count); } /// /// 发送多组数据 /// 向指定连接发送多组数据 /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) /// /// 连接 ID /// 发送缓冲区数组 /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 public bool SendPackets(IntPtr connId, T[] objects) { bool ret = false; WSABUF[] buffer = new WSABUF[objects.Length]; IntPtr[] ptrs = new IntPtr[buffer.Length]; try { for (int i = 0; i < objects.Length; i++) { buffer[i].Length = Marshal.SizeOf(typeof(T)); ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length); Marshal.StructureToPtr(objects[i], ptrs[i], true); buffer[i].Buffer = ptrs[i]; } ret = SendPackets(connId, buffer, buffer.Length); } catch (Exception ex) { throw ex; } finally { foreach (var ptr in ptrs) { if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); } } } return ret; } /// /// 断开与某个客户的连接 /// /// /// 是否强制断开 /// public bool Disconnect(IntPtr connId, bool force = true) { return Sdk.HP_Server_Disconnect(pServer, connId, force); } /// /// 断开超过指定时间的连接 /// /// 毫秒 /// 强制 /// public bool DisconnectLongConnections(uint period, bool force = true) { return Sdk.HP_Server_DisconnectLongConnections(pServer, period, force); } /// /// 暂停接收 /// /// /// public bool PauseReceive(IntPtr connId) { return Sdk.HP_Server_PauseReceive(pServer, connId, true); } /// /// 唤醒接收 /// /// /// public bool ResumeReceive(IntPtr connId) { return Sdk.HP_Server_PauseReceive(pServer, connId, false); } /// /// 获取连接的接收状态 /// /// /// public ReceiveState GetReceiveState(IntPtr connId) { int state = -1; if (Sdk.HP_Server_IsPauseReceive(pServer, connId, ref state)) { return (ReceiveState)state; } return ReceiveState.Unknown; } /// /// 断开超过指定时长的静默连接 /// /// 毫秒 /// 强制 /// public bool DisconnectSilenceConnections(uint period, bool force = true) { return Sdk.HP_Server_DisconnectSilenceConnections(pServer, period, force); } /// /// 获取某个连接的本地地址信息 /// /// /// /// /// public bool GetLocalAddress(IntPtr connId, ref string ip, ref ushort port) { int ipLength = 40; StringBuilder sb = new StringBuilder(ipLength); bool ret = Sdk.HP_Server_GetLocalAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; if (ret == true) { ip = sb.ToString(); } return ret; } /// /// 获取某个连接的远程地址信息 /// /// /// /// /// public bool GetRemoteAddress(IntPtr connId, ref string ip, ref ushort port) { int ipLength = 40; StringBuilder sb = new StringBuilder(ipLength); bool ret = Sdk.HP_Server_GetRemoteAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; if (ret == true) { ip = sb.ToString(); } return ret; } /// /// 获取连接中未发出数据的长度 /// /// /// /// public bool GetPendingDataLength(IntPtr connId, ref int length) { return Sdk.HP_Server_GetPendingDataLength(pServer, connId, ref length); } // 是否启动 public bool IsStarted { get { if (pServer == IntPtr.Zero) { return false; } return Sdk.HP_Server_HasStarted(pServer); } } /// /// 状态 /// public ServiceState State { get { return Sdk.HP_Server_GetState(pServer); } } /// /// 连接数 /// public uint ConnectionCount { get { return Sdk.HP_Server_GetConnectionCount(pServer); } } /// /// 检测是否为安全连接(SSL/HTTPS) /// public bool IsSecure { get { return Sdk.HP_Server_IsSecure(pServer); } } /// /// 获取所有连接,未获取到连接返回null /// /// public IntPtr[] GetAllConnectionIDs() { IntPtr[] arr = null; do { uint count = ConnectionCount; if (count == 0) { break; } arr = new IntPtr[count]; if (Sdk.HP_Server_GetAllConnectionIDs(pServer, arr, ref count)) { if (arr.Length > count) { IntPtr[] newArr = new IntPtr[count]; Array.Copy(arr, newArr, count); arr = newArr; } break; } } while (true); return arr; } /// /// 获取监听socket的地址信息 /// /// /// /// public bool GetListenAddress(ref string ip, ref ushort port) { int ipLength = 40; StringBuilder sb = new StringBuilder(ipLength); bool ret = Sdk.HP_Server_GetListenAddress(pServer, sb, ref ipLength, ref port); if (ret == true) { ip = sb.ToString(); } return ret; } /// /// 获取指定连接的连接时长(毫秒) /// /// /// /// public bool GetConnectPeriod(IntPtr connId, ref uint period) { return Sdk.HP_Server_GetConnectPeriod(pServer, connId, ref period); } /// /// 获取某个连接静默时间(毫秒) /// /// /// /// public bool GetSilencePeriod(IntPtr connId, ref uint period) { return Sdk.HP_Server_GetSilencePeriod(pServer, connId, ref period); } /// /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) /// public uint MaxConnectionCount { get { return Sdk.HP_Server_GetMaxConnectionCount(pServer); } set { Sdk.HP_Server_SetMaxConnectionCount(pServer, value); } } /// /// 读取或设置工作线程数量(通常设置为 2 * CPU + 2) /// public uint WorkerThreadCount { get { return Sdk.HP_Server_GetWorkerThreadCount(pServer); } set { Sdk.HP_Server_SetWorkerThreadCount(pServer, value); } } /// /// 读取或设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) /// public uint FreeSocketObjLockTime { get { return Sdk.HP_Server_GetFreeSocketObjLockTime(pServer); } set { Sdk.HP_Server_SetFreeSocketObjLockTime(pServer, value); } } /// /// 读取或设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) /// public uint FreeSocketObjPool { get { return Sdk.HP_Server_GetFreeSocketObjPool(pServer); } set { Sdk.HP_Server_SetFreeSocketObjPool(pServer, value); } } /// /// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) /// public uint FreeBufferObjPool { get { return Sdk.HP_Server_GetFreeBufferObjPool(pServer); } set { Sdk.HP_Server_SetFreeBufferObjPool(pServer, value); } } /// /// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) /// public uint FreeSocketObjHold { get { return Sdk.HP_Server_GetFreeSocketObjHold(pServer); } set { Sdk.HP_Server_SetFreeSocketObjHold(pServer, value); } } /// /// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) /// public uint FreeBufferObjHold { get { return Sdk.HP_Server_GetFreeBufferObjHold(pServer); } set { Sdk.HP_Server_SetFreeBufferObjHold(pServer, value); } } /// /// 读取或设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) /// public bool MarkSilence { get { return Sdk.HP_Server_IsMarkSilence(pServer); } set { Sdk.HP_Server_SetMarkSilence(pServer, value); } } /// /// 获取或设置数据发送策略 /// public SendPolicy SendPolicy { get { return Sdk.HP_Server_GetSendPolicy(pServer); } set { Sdk.HP_Server_SetSendPolicy(pServer, value); } } /// /// 获取或设置 OnSend 事件同步策略 /// public OnSendSyncPolicy OnSendSyncPolicy { get { return Sdk.HP_Server_GetOnSendSyncPolicy(pServer); } set { Sdk.HP_Server_SetOnSendSyncPolicy(pServer, value); } } /// /// 获取系统返回的错误码 /// public int SYSGetLastError() { return Sdk.SYS_GetLastError(); } /// /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 /// public int SYSWSAGetLastError() { return Sdk.SYS_WSAGetLastError(); } /// /// 获取错误码 /// public SocketError ErrorCode { get { return Sdk.HP_Server_GetLastError(pServer); } } /// /// 版本号 /// public string Version { get { return Sdk.GetHPSocketVersion(); } } /// /// 获取错误信息 /// public string ErrorMessage { get { IntPtr ptr = Sdk.HP_Server_GetLastErrorDesc(pServer); string desc = Marshal.PtrToStringAnsi(ptr); return desc; } } /////////////////////////////////////////////////////////////////////////////////////// protected Sdk.OnPrepareListen _OnPrepareListen = null; protected Sdk.OnAccept _OnAccept = null; protected Sdk.OnReceive _OnReceive = null; protected Sdk.OnSend _OnSend = null; protected Sdk.OnClose _OnClose = null; protected Sdk.OnShutdown _OnShutdown = null; protected Sdk.OnHandShake _OnHandShake = null; protected virtual void SetCallback() { _OnPrepareListen = new Sdk.OnPrepareListen(SDK_OnPrepareListen); _OnAccept = new Sdk.OnAccept(SDK_OnAccept); _OnSend = new Sdk.OnSend(SDK_OnSend); _OnReceive = new Sdk.OnReceive(SDK_OnReceive); _OnClose = new Sdk.OnClose(SDK_OnClose); _OnShutdown = new Sdk.OnShutdown(SDK_OnShutdown); _OnHandShake = new Sdk.OnHandShake(SDK_OnHandShake); Sdk.HP_Set_FN_Server_OnPrepareListen(pListener, _OnPrepareListen); Sdk.HP_Set_FN_Server_OnAccept(pListener, _OnAccept); Sdk.HP_Set_FN_Server_OnSend(pListener, _OnSend); Sdk.HP_Set_FN_Server_OnReceive(pListener, _OnReceive); Sdk.HP_Set_FN_Server_OnClose(pListener, _OnClose); Sdk.HP_Set_FN_Server_OnShutdown(pListener, _OnShutdown); Sdk.HP_Set_FN_Server_OnHandShake(pListener, _OnHandShake); } protected HandleResult SDK_OnHandShake(IntPtr pSender, IntPtr connId) { if (OnHandShake != null) { return OnHandShake(this, connId); } return HandleResult.Ignore; } protected HandleResult SDK_OnPrepareListen(IntPtr pSender, IntPtr soListen) { if (OnPrepareListen != null) { return OnPrepareListen(this, soListen); } return HandleResult.Ignore; } protected HandleResult SDK_OnAccept(IntPtr pSender, IntPtr connId, IntPtr pClient) { if (OnAccept != null) { return OnAccept(this, connId, pClient); } return HandleResult.Ignore; } protected HandleResult SDK_OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length) { if (OnSend != null) { byte[] bytes = new byte[length]; Marshal.Copy(pData, bytes, 0, length); return OnSend(this, connId, bytes); } return HandleResult.Ignore; } protected HandleResult SDK_OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length) { if (OnPointerDataReceive != null) { return OnPointerDataReceive(this, connId, pData, length); } else if (OnReceive != null) { byte[] bytes = new byte[length]; Marshal.Copy(pData, bytes, 0, length); return OnReceive(this, connId, bytes); } return HandleResult.Ignore; } protected HandleResult SDK_OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode) { if (OnClose != null) { return OnClose(this, connId, enOperation, errorCode); } return HandleResult.Ignore; } protected HandleResult SDK_OnShutdown(IntPtr pSender) { if (OnShutdown != null) { return OnShutdown(this); } return HandleResult.Ignore; } ///////////////////////////////////////////////////////////////////////// /// /// 根据错误码返回错误信息 /// /// /// public string GetSocketErrorDesc(SocketError code) { IntPtr ptr = Sdk.HP_GetSocketErrorDesc(code); string desc = Marshal.PtrToStringAnsi(ptr); return desc; } /// /// 调用系统的 setsockopt() /// /// /// /// /// /// /// /// public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len) { return Sdk.SYS_SetSocketOption(sock, level, name, val, len); } /// /// 调用系统的 getsockopt() /// /// /// /// /// /// /// /// public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len) { return Sdk.SYS_GetSocketOption(sock, level, name, val, ref len); } /// /// 调用系统的 ioctlsocket() /// /// /// /// /// /// public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg) { return Sdk.SYS_IoctlSocket(sock, cmd, arg); } } }