using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace HPSocketCS
{
public class TcpClientEvent
{
public delegate HandleResult OnPrepareConnectEventHandler(TcpClient sender, uint socket);
public delegate HandleResult OnConnectEventHandler(TcpClient sender);
public delegate HandleResult OnSendEventHandler(TcpClient sender, byte[] bytes);
public delegate HandleResult OnReceiveEventHandler(TcpClient sender, byte[] bytes);
public delegate HandleResult OnPointerDataReceiveEventHandler(TcpClient sender, IntPtr pData, int length);
public delegate HandleResult OnCloseEventHandler(TcpClient sender, SocketOperation enOperation, int errorCode);
}
public class TcpClient
{
protected IntPtr _pClient = IntPtr.Zero;
protected IntPtr pClient
{
get
{
return _pClient;
}
set
{
_pClient = value;
}
}
protected IntPtr pListener = IntPtr.Zero;
protected bool IsCreate = false;
ConnectionExtra ExtraData = new ConnectionExtra();
/****************************************************/
///
/// 准备连接了事件
///
public event TcpClientEvent.OnPrepareConnectEventHandler OnPrepareConnect;
///
/// 连接事件
///
public event TcpClientEvent.OnConnectEventHandler OnConnect;
///
/// 数据发送事件
///
public event TcpClientEvent.OnSendEventHandler OnSend;
///
/// 数据到达事件
///
public event TcpClientEvent.OnReceiveEventHandler OnReceive;
///
/// 数据到达事件(指针数据)
///
public event TcpClientEvent.OnPointerDataReceiveEventHandler OnPointerDataReceive;
///
/// 连接关闭事件
///
public event TcpClientEvent.OnCloseEventHandler OnClose;
public TcpClient()
{
CreateListener();
}
~TcpClient()
{
Destroy();
}
///
/// 创建socket监听&服务组件
///
///
protected virtual bool CreateListener()
{
if (IsCreate == true || pListener != IntPtr.Zero || pClient != IntPtr.Zero)
{
return false;
}
pListener = Sdk.Create_HP_TcpClientListener();
if (pListener == IntPtr.Zero)
{
return false;
}
pClient = Sdk.Create_HP_TcpClient(pListener);
if (pClient == IntPtr.Zero)
{
return false;
}
IsCreate = true;
return true;
}
///
/// 终止服务并释放资源
///
public virtual void Destroy()
{
Stop();
if (pClient != IntPtr.Zero)
{
Sdk.Destroy_HP_TcpClient(pClient);
pClient = IntPtr.Zero;
}
if (pListener != IntPtr.Zero)
{
Sdk.Destroy_HP_TcpClientListener(pListener);
pListener = IntPtr.Zero;
}
IsCreate = false;
}
///
/// 启动通讯组件并连接到服务器
///
/// 远程地址
/// 远程端口
/// 是否异步
///
public bool Connect(string address, ushort port, bool async = true)
{
if (string.IsNullOrEmpty(address) == true)
{
throw new Exception("address is null");
}
else if (port == 0)
{
throw new Exception("port is zero");
}
if (IsStarted == true)
{
return false;
}
this.SetCallback();
return Sdk.HP_Client_Start(pClient, address, port, async);
}
///
/// 启动通讯组件并连接到服务器
///
/// 远程地址
/// 远程端口
/// 本地绑定到哪个ip?,多ip下可以选择绑定到指定ip
/// 是否异步
///
public bool Connect(string address, ushort port, string bindAddress, bool async = true)
{
if (string.IsNullOrEmpty(address) == true)
{
throw new Exception("address is null");
}
else if (port == 0)
{
throw new Exception("port is zero");
}
if (IsStarted == true)
{
return false;
}
this.SetCallback();
return Sdk.HP_Client_StartWithBindAddress(pClient, address, port, async, bindAddress);
}
///
/// 停止通讯组件
///
///
public bool Stop()
{
if (IsStarted == false)
{
return false;
}
return Sdk.HP_Client_Stop(pClient);
}
///
/// 发送数据
///
///
///
///
///
public bool Send(byte[] bytes, int size)
{
return Sdk.HP_Client_Send(pClient, bytes, size);
}
///
/// 发送数据
///
///
///
///
///
public bool Send(IntPtr bufferPtr, int size)
{
return Sdk.HP_Client_Send(pClient, bufferPtr, size);
}
///
/// 发送数据
///
///
///
///
///
public bool Send(T obj)
{
byte[] buffer = StructureToByte(obj);
return Send(buffer, buffer.Length);
}
///
/// 序列化对象后发送数据,序列化对象所属类必须标记[Serializable]
///
///
///
///
///
public bool SendBySerializable(object obj)
{
byte[] buffer = ObjectToBytes(obj);
return Send(buffer, buffer.Length);
}
///
/// 发送数据
///
///
///
/// 针对bytes的偏移
/// 发多大
///
public bool Send(byte[] bytes, int offset, int size)
{
return Sdk.HP_Client_SendPart(pClient, bytes, size, offset);
}
///
/// 发送数据
///
///
///
/// 针对bufferPtr的偏移
/// 发多大
///
public bool Send(IntPtr bufferPtr, int offset, int size)
{
return Sdk.HP_Client_SendPart(pClient, bufferPtr, size, offset);
}
///
/// 发送多组数据
/// 向指定连接发送多组数据
/// TCP - 顺序发送所有数据包
///
/// 连接 ID
/// 发送缓冲区数组
/// 发送缓冲区数目
/// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendPackets(WSABUF[] buffers, int count)
{
return Sdk.HP_Client_SendPackets(pClient, buffers, count);
}
///
/// 发送多组数据
/// 向指定连接发送多组数据
/// TCP - 顺序发送所有数据包
///
/// 连接 ID
/// 发送缓冲区数组
/// 发送缓冲区数目
/// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendPackets(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(buffer, buffer.Length);
}
catch (Exception ex)
{
throw ex;
}
finally
{
for (int i = 0; i < ptrs.Length; i++)
{
if (ptrs[i] != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptrs[i]);
}
}
}
return ret;
}
///
/// 名称:发送小文件
/// 描述:向指定连接发送 4096 KB 以下的小文件
///
/// 文件路径
/// 头部附加数据
/// 尾部附加数据
/// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(string filePath, ref WSABUF head, ref WSABUF tail)
{
return Sdk.HP_TcpClient_SendSmallFile(pClient, filePath, ref head, ref tail);
}
///
/// 名称:发送小文件
/// 描述:向指定连接发送 4096 KB 以下的小文件
///
/// 文件路径
/// 头部附加数据,可以为null
/// 尾部附加数据,可以为null
/// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(string filePath, byte[] head, byte[] tail)
{
IntPtr pHead = IntPtr.Zero;
IntPtr pTail = IntPtr.Zero;
WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead };
WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail };
if (head != null)
{
wsaHead.Length = head.Length;
wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0);
}
if (tail != null)
{
wsaHead.Length = tail.Length;
wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0);
}
return SendSmallFile(filePath, ref wsaHead, ref wsatail);
}
///
/// 名称:发送小文件
/// 描述:向指定连接发送 4096 KB 以下的小文件
///
/// 文件路径
/// 头部附加数据,可以为null
/// 尾部附加数据,可以为null
/// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(string filePath, T1 head, T2 tail)
{
byte[] headBuffer = null;
if (head != null)
{
headBuffer = StructureToByte(head);
}
byte[] tailBuffer = null;
if (tail != null)
{
tailBuffer = StructureToByte(tail);
}
return SendSmallFile(filePath, headBuffer, tailBuffer);
}
///
/// 获取错误码
///
public SocketError ErrorCode
{
get
{
return Sdk.HP_Client_GetLastError(pClient);
}
}
///
/// 获取错误信息
///
public string ErrorMessage
{
get
{
IntPtr ptr = Sdk.HP_Client_GetLastErrorDesc(pClient);
string desc = Marshal.PtrToStringUni(ptr);
return desc;
}
}
///
///
///
///
///
public bool GetPendingDataLength(ref int length)
{
return Sdk.HP_Client_GetPendingDataLength(pClient, ref length);
}
///
/// 获取附加数据
///
///
public T GetExtra()
{
IntPtr key = (IntPtr)this.GetHashCode();
return (T)ExtraData.GetExtra(key);
}
///
/// 设置附加数据
///
///
///
///
public bool SetExtra(object newValue)
{
IntPtr key = (IntPtr)this.GetHashCode();
return ExtraData.SetExtra(key, newValue);
}
///
/// 删除附加数据
///
///
///
public bool RemoveExtra()
{
IntPtr key = (IntPtr)this.GetHashCode();
return ExtraData.RemoveExtra(key);
}
/////
///// 设置连接的附加数据
/////
/////
///// 如果为null,则为释放设置的数据
/////
//public void SetExtra(object obj)
//{
// // 释放附加数据
// IntPtr ptr = Sdk.HP_Client_GetExtra(pClient);
// if (ptr != IntPtr.Zero)
// {
// Marshal.FreeHGlobal(ptr);
// ptr = IntPtr.Zero;
// }
// if (obj != null)
// {
// // 设置附加数据
// ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
// Marshal.StructureToPtr(obj, ptr, false);
// }
// Sdk.HP_Client_SetExtra(pClient, ptr);
//}
/////
///// 获取附加数据
///// 如设置的是个结构体/类对象,可以用 Type objA = (Type)Marshal.PtrToStructure(ptr, typeof(Type)) 获取
///// 其中Type是结构体/类名,ptr是该方法的传出值,在该方法返回为true的时候可用
/////
/////
/////
/////
//public T GetExtra()
//{
// IntPtr ptr = Sdk.HP_Client_GetExtra(pClient);
// T obj = default(T);
// if (ptr != IntPtr.Zero)
// {
// obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
// }
// return obj;
//}
/////
///// 移除连接中的附加数据, 同SetExtra(null)
/////
/////
/////
//public void RemoveExtra()
//{
// SetExtra(null);
//}
/////
///// 获取或这是附加数据
///// 推荐使用泛型方法:T GetExtra()
/////
//public object Extra
//{
// get
// {
// return GetExtra