完善事件代码和整理说明
This commit is contained in:
parent
2659a11858
commit
dcd4166dc3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -13,7 +13,7 @@ namespace HaoYueNet.ClientNetwork
|
||||
/// <summary>
|
||||
/// 心跳包数据
|
||||
/// </summary>
|
||||
private byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 };
|
||||
static byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
////响应倒计时计数最大值
|
||||
//private static int MaxRevIndexNum = 6;
|
||||
@ -78,13 +78,13 @@ namespace HaoYueNet.ClientNetwork
|
||||
_heartTimer.Enabled = true;
|
||||
LogOut("开启心跳包检测");
|
||||
|
||||
OnConnected(true);
|
||||
OnConnected?.Invoke(true);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogOut("连接失败:" + ex.ToString());
|
||||
OnConnected(false);
|
||||
OnConnected?.Invoke(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -172,24 +172,20 @@ namespace HaoYueNet.ClientNetwork
|
||||
SendToSocket(_finaldata);
|
||||
}
|
||||
|
||||
public delegate void OnDataCallBack_Data(int CMDID, int ERRCODE, byte[] data);
|
||||
|
||||
public event OnDataCallBack_Data OnDataCallBack;
|
||||
|
||||
public delegate void delegate_NoData();
|
||||
|
||||
public delegate void delegate_Bool(bool IsConnected);
|
||||
|
||||
public event delegate_NoData OnClose;
|
||||
|
||||
public event delegate_Bool OnConnected;
|
||||
|
||||
public delegate void delegate_str(string Msg);
|
||||
#region 事件定义
|
||||
public delegate void OnReceiveDataHandler(int CMDID, int ERRCODE, byte[] data);
|
||||
public delegate void OnConnectedHandler(bool IsConnected);
|
||||
public delegate void OnCloseHandler();
|
||||
public delegate void OnLogOutHandler(string Msg);
|
||||
#endregion
|
||||
|
||||
public event OnConnectedHandler OnConnected;
|
||||
public event OnReceiveDataHandler OnReceiveData;
|
||||
public event OnCloseHandler OnClose;
|
||||
/// <summary>
|
||||
/// 网络库调试日志输出
|
||||
/// </summary>
|
||||
public event delegate_str OnLogOut;
|
||||
public event OnLogOutHandler OnLogOut;
|
||||
|
||||
///// <summary>
|
||||
///// 用于调用者回调的虚函数
|
||||
@ -220,7 +216,7 @@ namespace HaoYueNet.ClientNetwork
|
||||
LogOut("关闭连接");
|
||||
//关闭Socket连接
|
||||
client.Close();
|
||||
OnClose();
|
||||
OnClose?.Invoke();
|
||||
}
|
||||
|
||||
|
||||
@ -246,8 +242,8 @@ namespace HaoYueNet.ClientNetwork
|
||||
}
|
||||
|
||||
HunterNet_S2C _c2s = DeSerizlize<HunterNet_S2C>(data);
|
||||
|
||||
OnDataCallBack(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray());
|
||||
|
||||
OnReceiveData(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray());
|
||||
}
|
||||
|
||||
private void Recive(object o)
|
||||
@ -356,7 +352,7 @@ namespace HaoYueNet.ClientNetwork
|
||||
public void LogOut(string Msg)
|
||||
{
|
||||
//Console.WriteLine(Msg);
|
||||
OnLogOut(Msg);
|
||||
OnLogOut?.Invoke(Msg);
|
||||
}
|
||||
|
||||
public Socket GetClientSocket()
|
||||
|
@ -59,6 +59,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="NetworkHelperCore.cs" />
|
||||
<Compile Include="NetworkHelperP2PCore.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ProtobufHunterNetCore.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -16,7 +16,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
/// <summary>
|
||||
/// 心跳包数据
|
||||
/// </summary>
|
||||
private byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 };
|
||||
static byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
////响应倒计时计数最大值
|
||||
//private static int MaxRevIndexNum = 6;
|
||||
@ -31,16 +31,16 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
private static int MaxSendIndexNum = 3;
|
||||
|
||||
//响应倒计时计数
|
||||
private static int RevIndex=0;
|
||||
private static int RevIndex = 0;
|
||||
//发送倒计时计数
|
||||
private static int SendIndex=0;
|
||||
private static int SendIndex = 0;
|
||||
|
||||
//计时器间隔
|
||||
private static int TimerInterval = 3000;
|
||||
|
||||
private System.Timers.Timer _heartTimer;
|
||||
|
||||
public void Init(string IP, int port, bool bBindReuseAddress = false,int bBindport = 0)
|
||||
public void Init(string IP, int port, bool bBindReuseAddress = false, int bBindport = 0)
|
||||
{
|
||||
|
||||
LogOut("==>初始化网络核心");
|
||||
@ -81,13 +81,13 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
_heartTimer.Enabled = true;
|
||||
LogOut("开启心跳包检测");
|
||||
|
||||
OnConnected(true);
|
||||
OnConnected?.Invoke(true);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogOut("连接失败:" + ex.ToString());
|
||||
OnConnected(false);
|
||||
OnConnected?.Invoke(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -165,7 +165,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
/// </summary>
|
||||
/// <param name="CMDID"></param>
|
||||
/// <param name="data">序列化之后的数据</param>
|
||||
public void SendToServer(int CMDID,byte[] data)
|
||||
public void SendToServer(int CMDID, byte[] data)
|
||||
{
|
||||
//LogOut("准备数据 CMDID=> "+CMDID);
|
||||
HunterNet_C2S _c2sdata = new HunterNet_C2S();
|
||||
@ -175,24 +175,20 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
SendToSocket(_finaldata);
|
||||
}
|
||||
|
||||
public delegate void OnDataCallBack_Data(int CMDID, int ERRCODE, byte[] data);
|
||||
|
||||
public event OnDataCallBack_Data OnDataCallBack;
|
||||
|
||||
public delegate void delegate_NoData();
|
||||
|
||||
public delegate void delegate_Bool(bool IsConnected);
|
||||
|
||||
public event delegate_NoData OnClose;
|
||||
|
||||
public event delegate_Bool OnConnected;
|
||||
|
||||
public delegate void delegate_str(string Msg);
|
||||
#region 事件定义
|
||||
public delegate void OnReceiveDataHandler(int CMDID, int ERRCODE, byte[] data);
|
||||
public delegate void OnConnectedHandler(bool IsConnected);
|
||||
public delegate void OnCloseHandler();
|
||||
public delegate void OnLogOutHandler(string Msg);
|
||||
#endregion
|
||||
|
||||
public event OnConnectedHandler OnConnected;
|
||||
public event OnReceiveDataHandler OnReceiveData;
|
||||
public event OnCloseHandler OnClose;
|
||||
/// <summary>
|
||||
/// 网络库调试日志输出
|
||||
/// </summary>
|
||||
public event delegate_str OnLogOut;
|
||||
public event OnLogOutHandler OnLogOut;
|
||||
|
||||
///// <summary>
|
||||
///// 用于调用者回调的虚函数
|
||||
@ -223,7 +219,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
LogOut("关闭连接");
|
||||
//关闭Socket连接
|
||||
client.Close();
|
||||
OnClose();
|
||||
OnClose?.Invoke();
|
||||
}
|
||||
|
||||
|
||||
@ -234,7 +230,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
{
|
||||
OnCloseReady();
|
||||
}
|
||||
|
||||
|
||||
private void DataCallBackReady(byte[] data)
|
||||
{
|
||||
|
||||
@ -247,10 +243,10 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
//LogOut("收到心跳包");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
HunterNet_S2C _c2s = DeSerizlize<HunterNet_S2C>(data);
|
||||
|
||||
OnDataCallBack(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray());
|
||||
|
||||
OnReceiveData(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray());
|
||||
}
|
||||
|
||||
private void Recive(object o)
|
||||
@ -261,7 +257,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
while (true)
|
||||
{
|
||||
byte[] buffer = new byte[1024 * 1024 * 2];
|
||||
int effective=0;
|
||||
int effective = 0;
|
||||
try
|
||||
{
|
||||
effective = client.Receive(buffer);
|
||||
@ -270,7 +266,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
//远程主机强迫关闭了一个现有的连接
|
||||
OnCloseReady();
|
||||
@ -312,7 +308,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
else
|
||||
{
|
||||
//把头去掉,就可以吃了,蛋白质是牛肉的六倍
|
||||
DataCallBackReady(getData.Skip(StartIndex+4).Take(HeadLength-4).ToArray());
|
||||
DataCallBackReady(getData.Skip(StartIndex + 4).Take(HeadLength - 4).ToArray());
|
||||
StartIndex += HeadLength;//当读取一条完整的数据后,读取数据的起始下标应为当前接受到的消息体的长度(当前数据的尾部或下一条消息的首部)
|
||||
}
|
||||
}
|
||||
@ -359,7 +355,7 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
public void LogOut(string Msg)
|
||||
{
|
||||
//Console.WriteLine(Msg);
|
||||
OnLogOut(Msg);
|
||||
OnLogOut?.Invoke(Msg);
|
||||
}
|
||||
|
||||
public Socket GetClientSocket()
|
||||
@ -367,4 +363,4 @@ namespace HaoYueNet.ClientNetworkNet4x
|
||||
return client;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,13 +14,12 @@ using static Google.Protobuf.Reflection.FieldOptions.Types;
|
||||
|
||||
namespace HaoYueNet.ServerNetwork
|
||||
{
|
||||
public class SocketManager
|
||||
public class TcpSaeaServer
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 心跳包数据
|
||||
/// </summary>
|
||||
private byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 };
|
||||
static byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 };
|
||||
//响应倒计时计数最大值
|
||||
//public int MaxRevIndexNum { get; set; } = 5;
|
||||
////发送倒计时计数最大值
|
||||
@ -30,90 +29,69 @@ namespace HaoYueNet.ServerNetwork
|
||||
public int MaxRevIndexNum { get; set; } = 50;
|
||||
//发送倒计时计数最大值
|
||||
public int MaxSendIndexNum { get; set; } = 3;
|
||||
|
||||
//计时器间隔
|
||||
private static int TimerInterval = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// 心跳包计数器
|
||||
/// </summary>
|
||||
private System.Timers.Timer _heartTimer;
|
||||
|
||||
public int m_maxConnectNum; //最大连接数
|
||||
public int m_revBufferSize; //最大接收字节数
|
||||
public BufferManager m_bufferManager;
|
||||
public const int opsToAlloc = 2;
|
||||
protected BufferManager m_bufferManager;
|
||||
protected const int opsToAlloc = 2;
|
||||
Socket listenSocket; //监听Socket
|
||||
public SocketEventPool m_Receivepool;
|
||||
|
||||
public SocketEventPool m_Sendpool;
|
||||
public TokenMsgPool msg_pool;
|
||||
public int m_clientCount; //连接的客户端数量
|
||||
public Semaphore m_maxNumberAcceptedClients;//信号量
|
||||
|
||||
protected SocketEventPool m_Receivepool;
|
||||
protected SocketEventPool m_Sendpool;
|
||||
protected TokenMsgPool msg_pool;
|
||||
protected int m_clientCount; //连接的客户端数量
|
||||
protected Semaphore m_maxNumberAcceptedClients;//信号量
|
||||
List<AsyncUserToken> m_clients; //客户端列表
|
||||
public Dictionary<Socket, AsyncUserToken> _DictSocketAsyncUserToken = new Dictionary<Socket, AsyncUserToken>();
|
||||
|
||||
protected Dictionary<Socket, AsyncUserToken> _DictSocketAsyncUserToken = new Dictionary<Socket, AsyncUserToken>();
|
||||
|
||||
|
||||
#region Token管理
|
||||
|
||||
void ClearUserToken()
|
||||
{
|
||||
lock (_DictSocketAsyncUserToken)
|
||||
{
|
||||
m_clients.Clear();
|
||||
_DictSocketAsyncUserToken.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void AddUserToken(AsyncUserToken userToken)
|
||||
{
|
||||
lock (_DictSocketAsyncUserToken)
|
||||
{
|
||||
m_clients.Add(userToken);
|
||||
_DictSocketAsyncUserToken.Add(userToken.Socket, userToken);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveUserToken(AsyncUserToken userToken)
|
||||
{
|
||||
lock (_DictSocketAsyncUserToken)
|
||||
{
|
||||
m_clients.Remove(userToken);
|
||||
_DictSocketAsyncUserToken.Remove(userToken.Socket);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 定义委托
|
||||
|
||||
/// <summary>
|
||||
/// 客户端连接数量变化时触发
|
||||
/// </summary>
|
||||
/// <param name="num">当前增加客户的个数(用户退出时为负数,增加时为正数,一般为1)</param>
|
||||
/// <param name="token">增加用户的信息</param>
|
||||
public delegate void OnClientNumberChange(int num, AsyncUserToken token);
|
||||
|
||||
public delegate void OnClientNumberChangeHandler(int num, AsyncUserToken token);
|
||||
/// <summary>
|
||||
/// 接收到客户端的数据
|
||||
/// </summary>
|
||||
/// <param name="token">客户端</param>
|
||||
/// <param name="buff">客户端数据</param>
|
||||
public delegate void OnReceiveData(AsyncUserToken token, byte[] buff);
|
||||
|
||||
public delegate void OnReceiveDataHandler(AsyncUserToken sk, int CMDID, byte[] data);
|
||||
/// <summary>
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
/// <param name="sk"></param>
|
||||
public delegate void OnDisconnectHandler(AsyncUserToken sk);
|
||||
/// <summary>
|
||||
/// 日志
|
||||
/// </summary>
|
||||
/// <param name="sk"></param>
|
||||
public delegate void OnNetLogHandler(string msg);
|
||||
#endregion
|
||||
|
||||
#region 定义事件
|
||||
/// <summary>
|
||||
/// 客户端连接数量变化事件
|
||||
/// </summary>
|
||||
public event OnClientNumberChange ClientNumberChange;
|
||||
|
||||
/// </summary>
|
||||
public event OnClientNumberChangeHandler OnClientNumberChange;
|
||||
/// <summary>
|
||||
/// 接收到客户端的数据事件
|
||||
/// </summary>
|
||||
public event OnReceiveData ReceiveClientData;
|
||||
/// </summary>
|
||||
public event OnReceiveDataHandler OnReceive;
|
||||
/// <summary>
|
||||
/// 接收到客户端的断开连接
|
||||
/// </summary>
|
||||
public event OnDisconnectHandler OnDisconnected;
|
||||
/// <summary>
|
||||
/// 网络库内部输出
|
||||
/// </summary>
|
||||
public event OnNetLogHandler OnNetLog;
|
||||
#endregion
|
||||
|
||||
#region 定义属性
|
||||
@ -128,7 +106,7 @@ namespace HaoYueNet.ServerNetwork
|
||||
/// </summary>
|
||||
/// <param name="numConnections">最大连接数</param>
|
||||
/// <param name="receiveBufferSize">缓存区大小</param>
|
||||
public SocketManager(int numConnections, int receiveBufferSize)
|
||||
public TcpSaeaServer(int numConnections, int receiveBufferSize)
|
||||
{
|
||||
m_clientCount = 0;
|
||||
m_maxConnectNum = numConnections;
|
||||
@ -145,6 +123,7 @@ namespace HaoYueNet.ServerNetwork
|
||||
m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
|
||||
}
|
||||
|
||||
#region 连接操作
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
/// </summary>
|
||||
@ -179,16 +158,16 @@ namespace HaoYueNet.ServerNetwork
|
||||
|
||||
m_Sendpool.Push(readWriteEventArg);
|
||||
}
|
||||
OutNetLog("初始化完毕");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 启动服务
|
||||
/// </summary>
|
||||
/// <param name="localEndPoint"></param>
|
||||
/// <param name="bReuseAddress">是否端口重用</param>
|
||||
/// <returns></returns>
|
||||
public bool Start(IPEndPoint localEndPoint,bool bReuseAddress = false)
|
||||
public bool Start(IPEndPoint localEndPoint, bool bReuseAddress = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -206,12 +185,14 @@ namespace HaoYueNet.ServerNetwork
|
||||
// post accepts on the listening socket
|
||||
StartAccept(null);
|
||||
|
||||
OutNetLog("监听:" + listenSocket.AddressFamily.ToString());
|
||||
|
||||
_heartTimer = new System.Timers.Timer();
|
||||
_heartTimer.Interval = TimerInterval;
|
||||
_heartTimer.Elapsed += CheckUpdatetimer_Elapsed;
|
||||
_heartTimer.AutoReset = true;
|
||||
_heartTimer.Enabled = true;
|
||||
//Console.WriteLine("开启心跳包定时器");
|
||||
OutNetLog("开启定时心跳包");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -244,11 +225,10 @@ namespace HaoYueNet.ServerNetwork
|
||||
int c_count = m_clients.Count;
|
||||
ClearUserToken();
|
||||
|
||||
if (ClientNumberChange != null)
|
||||
ClientNumberChange(-c_count, null);
|
||||
if (OnClientNumberChange != null)
|
||||
OnClientNumberChange(-c_count, null);
|
||||
}
|
||||
|
||||
|
||||
public void CloseClient(AsyncUserToken token)
|
||||
{
|
||||
try
|
||||
@ -258,7 +238,66 @@ namespace HaoYueNet.ServerNetwork
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
//关闭客户端连接
|
||||
private void CloseClientSocket(SocketAsyncEventArgs e)
|
||||
{
|
||||
AsyncUserToken token = e.UserToken as AsyncUserToken;
|
||||
|
||||
//调用关闭连接
|
||||
OnDisconnected?.Invoke(token);
|
||||
|
||||
RemoveUserToken(token);
|
||||
|
||||
//如果有事件,则调用事件,发送客户端数量变化通知
|
||||
OnClientNumberChange?.Invoke(-1, token);
|
||||
|
||||
// close the socket associated with the client
|
||||
try
|
||||
{
|
||||
token.Socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
catch (Exception) { }
|
||||
token.Socket.Close();
|
||||
// decrement the counter keeping track of the total number of clients connected to the server
|
||||
Interlocked.Decrement(ref m_clientCount);
|
||||
m_maxNumberAcceptedClients.Release();
|
||||
// Free the SocketAsyncEventArg so they can be reused by another client
|
||||
ReleaseSocketAsyncEventArgs(e);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Token管理
|
||||
void AddUserToken(AsyncUserToken userToken)
|
||||
{
|
||||
lock (_DictSocketAsyncUserToken)
|
||||
{
|
||||
m_clients.Add(userToken);
|
||||
_DictSocketAsyncUserToken.Add(userToken.Socket, userToken);
|
||||
}
|
||||
}
|
||||
void RemoveUserToken(AsyncUserToken userToken)
|
||||
{
|
||||
lock (_DictSocketAsyncUserToken)
|
||||
{
|
||||
m_clients.Remove(userToken);
|
||||
_DictSocketAsyncUserToken.Remove(userToken.Socket);
|
||||
}
|
||||
}
|
||||
void ClearUserToken()
|
||||
{
|
||||
lock (_DictSocketAsyncUserToken)
|
||||
{
|
||||
m_clients.Clear();
|
||||
_DictSocketAsyncUserToken.Clear();
|
||||
}
|
||||
}
|
||||
public AsyncUserToken GetAsyncUserTokenForSocket(Socket sk)
|
||||
{
|
||||
return _DictSocketAsyncUserToken.ContainsKey(sk) ? _DictSocketAsyncUserToken[sk] : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 监听客户端建立连接
|
||||
// Begins an operation to accept a connection request from the client
|
||||
//
|
||||
// <param name="acceptEventArg">The context object to use when issuing
|
||||
@ -311,7 +350,7 @@ namespace HaoYueNet.ServerNetwork
|
||||
|
||||
AddUserToken(userToken);
|
||||
|
||||
ClientNumberChange?.Invoke(1, userToken);
|
||||
OnClientNumberChange?.Invoke(1, userToken);
|
||||
if (!e.AcceptSocket.ReceiveAsync(readEventArgs))
|
||||
{
|
||||
ProcessReceive(readEventArgs);
|
||||
@ -326,25 +365,9 @@ namespace HaoYueNet.ServerNetwork
|
||||
if (e.SocketError == SocketError.OperationAborted) return;
|
||||
StartAccept(e);
|
||||
}
|
||||
#endregion
|
||||
|
||||
void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
// determine which type of operation just completed and call the associated handler
|
||||
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceive(e);
|
||||
break;
|
||||
case SocketAsyncOperation.Send:
|
||||
ProcessSend(e);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#region 完成端口收发处理
|
||||
// This method is invoked when an asynchronous receive operation completes.
|
||||
// If the remote host closed the connection, then the socket is closed.
|
||||
// If data was received then the data is echoed back to the client.
|
||||
@ -364,15 +387,8 @@ namespace HaoYueNet.ServerNetwork
|
||||
{
|
||||
token.Buffer.AddRange(data);
|
||||
}
|
||||
//注意:你一定会问,这里为什么要用do-while循环?
|
||||
//如果当客户发送大数据流的时候,e.BytesTransferred的大小就会比客户端发送过来的要小,
|
||||
//需要分多次接收.所以收到包的时候,先判断包头的大小.够一个完整的包再处理.
|
||||
//如果客户短时间内发送多个小数据包时, 服务器可能会一次性把他们全收了.
|
||||
//这样如果没有一个循环来控制,那么只会处理第一个包,
|
||||
//剩下的包全部留在token.Buffer中了,只有等下一个数据包过来后,才会放出一个来.
|
||||
do
|
||||
{
|
||||
|
||||
//如果包头不完整
|
||||
if (token.Buffer.Count < 4)
|
||||
break;
|
||||
@ -392,9 +408,6 @@ namespace HaoYueNet.ServerNetwork
|
||||
{
|
||||
token.Buffer.RemoveRange(0, packageLen + 4);
|
||||
}
|
||||
//将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度.
|
||||
if (ReceiveClientData != null)
|
||||
ReceiveClientData(token, rev);
|
||||
|
||||
DataCallBackReady(token, rev);
|
||||
|
||||
@ -418,7 +431,6 @@ namespace HaoYueNet.ServerNetwork
|
||||
//RuncomLib.Log.LogUtils.Info(xe.Message + "\r\n" + xe.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessSend(SocketAsyncEventArgs e)
|
||||
{
|
||||
if (e.SocketError == SocketError.Success)
|
||||
@ -433,34 +445,29 @@ namespace HaoYueNet.ServerNetwork
|
||||
ReleaseSocketAsyncEventArgs(e);
|
||||
SendForMsgPool();
|
||||
}
|
||||
|
||||
//关闭客户端
|
||||
private void CloseClientSocket(SocketAsyncEventArgs e)
|
||||
void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
AsyncUserToken token = e.UserToken as AsyncUserToken;
|
||||
// determine which type of operation just completed and call the associated handler
|
||||
|
||||
//调用关闭连接
|
||||
OnClose(token);
|
||||
|
||||
RemoveUserToken(token);
|
||||
|
||||
//如果有事件,则调用事件,发送客户端数量变化通知
|
||||
if (ClientNumberChange != null)
|
||||
ClientNumberChange(-1, token);
|
||||
// close the socket associated with the client
|
||||
try
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
token.Socket.Shutdown(SocketShutdown.Send);
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceive(e);
|
||||
break;
|
||||
case SocketAsyncOperation.Send:
|
||||
ProcessSend(e);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
|
||||
}
|
||||
catch (Exception) { }
|
||||
token.Socket.Close();
|
||||
// decrement the counter keeping track of the total number of clients connected to the server
|
||||
Interlocked.Decrement(ref m_clientCount);
|
||||
m_maxNumberAcceptedClients.Release();
|
||||
// Free the SocketAsyncEventArg so they can be reused by another client
|
||||
ReleaseSocketAsyncEventArgs(e);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 回收SocketAsyncEventArgs
|
||||
/// </summary>
|
||||
/// <param name="saea"></param>
|
||||
void ReleaseSocketAsyncEventArgs(SocketAsyncEventArgs saea)
|
||||
{
|
||||
saea.UserToken = null;//TODO
|
||||
@ -477,7 +484,7 @@ namespace HaoYueNet.ServerNetwork
|
||||
}
|
||||
|
||||
int sendrun = 0;
|
||||
public void SendForMsgPool()
|
||||
private void SendForMsgPool()
|
||||
{
|
||||
//if (flag_SendForMsgPool) return;
|
||||
try
|
||||
@ -491,21 +498,21 @@ namespace HaoYueNet.ServerNetwork
|
||||
try
|
||||
{
|
||||
TokenWithMsg msg = msg_pool.Dequeue();
|
||||
//Console.WriteLine("从信息池取出发送");
|
||||
//OutNetLog("从信息池取出发送");
|
||||
SendMessage(msg.token, msg.message);
|
||||
msg = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("==============================================>");
|
||||
OutNetLog("==============================================>");
|
||||
}
|
||||
}
|
||||
sendrun--;
|
||||
Console.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
OutNetLog("!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
OutNetLog(ex.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
@ -539,13 +546,13 @@ namespace HaoYueNet.ServerNetwork
|
||||
{
|
||||
//先压入队列,等待m_Sendpool回收
|
||||
msg_pool.Enqueue(new TokenWithMsg() { token = token, message = message });
|
||||
//Console.WriteLine("!!!!压入消息发送队列MSG_Pool");
|
||||
//OutNetLog("!!!!压入消息发送队列MSG_Pool");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
OutNetLog(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,33 +577,15 @@ namespace HaoYueNet.ServerNetwork
|
||||
}
|
||||
|
||||
#region
|
||||
|
||||
/// <summary>
|
||||
/// 用于调用者回调的虚函数
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public virtual void DataCallBack(AsyncUserToken sk, int CMDID, byte[] data)
|
||||
private void OnCloseReady(AsyncUserToken token)
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
/// <param name="sk"></param>
|
||||
public virtual void OnClose(AsyncUserToken sk)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void OnCloseReady(AsyncUserToken token)
|
||||
{
|
||||
OnClose(token);
|
||||
OnDisconnected?.Invoke(token);
|
||||
|
||||
RemoveUserToken(token);
|
||||
|
||||
//如果有事件,则调用事件,发送客户端数量变化通知
|
||||
if (ClientNumberChange != null)
|
||||
ClientNumberChange(-1, token);
|
||||
//如果有事件,则调用事件,发送客户端数量变化通知
|
||||
OnClientNumberChange?.Invoke(-1, token);
|
||||
|
||||
// close the socket associated with the client
|
||||
try
|
||||
{
|
||||
@ -619,7 +608,6 @@ namespace HaoYueNet.ServerNetwork
|
||||
{
|
||||
//发送数据
|
||||
SendMessage(token, data);
|
||||
|
||||
token.SendIndex = MaxSendIndexNum;
|
||||
}
|
||||
catch
|
||||
@ -628,11 +616,6 @@ namespace HaoYueNet.ServerNetwork
|
||||
}
|
||||
}
|
||||
|
||||
public AsyncUserToken GetAsyncUserTokenForSocket(Socket sk)
|
||||
{
|
||||
return _DictSocketAsyncUserToken.ContainsKey(sk) ? _DictSocketAsyncUserToken[sk] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对外暴露的发送消息
|
||||
/// </summary>
|
||||
@ -649,6 +632,40 @@ namespace HaoYueNet.ServerNetwork
|
||||
SendWithIndex(token, _finaldata);
|
||||
}
|
||||
|
||||
private void DataCallBackReady(AsyncUserToken sk, byte[] data)
|
||||
{
|
||||
//增加接收计数
|
||||
sk.RevIndex = MaxRevIndexNum;
|
||||
|
||||
if (data.Length == 1 && data[0] == 0x00)//心跳包
|
||||
{
|
||||
//OutNetLog("收到心跳包");
|
||||
//无处理
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
HunterNet_C2S _s2c = DeSerizlize<HunterNet_C2S>(data);
|
||||
//将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度.
|
||||
OnReceive?.Invoke(sk, (int)_s2c.HunterNetCoreCmdID, _s2c.HunterNetCoreData.ToArray());
|
||||
//DataCallBack(sk, (int)_s2c.HunterNetCoreCmdID, _s2c.HunterNetCoreData.ToArray());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OutNetLog("数据解析错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OutNetLog(string msg)
|
||||
{
|
||||
OnNetLog?.Invoke(msg);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 心跳包
|
||||
|
||||
/// <summary>
|
||||
/// 发送心跳包
|
||||
/// </summary>
|
||||
@ -660,7 +677,7 @@ namespace HaoYueNet.ServerNetwork
|
||||
return;
|
||||
try
|
||||
{
|
||||
//Console.WriteLine(DateTime.Now.ToString() + "发送心跳包");
|
||||
//OutNetLog(DateTime.Now.ToString() + "发送心跳包");
|
||||
token.SendIndex = MaxSendIndexNum;
|
||||
SendMessage(token, HeartbeatData, true);
|
||||
}
|
||||
@ -669,31 +686,6 @@ namespace HaoYueNet.ServerNetwork
|
||||
OnCloseReady(token);
|
||||
}
|
||||
}
|
||||
|
||||
private void DataCallBackReady(AsyncUserToken sk, byte[] data)
|
||||
{
|
||||
//增加接收计数
|
||||
sk.RevIndex = MaxRevIndexNum;
|
||||
|
||||
if (data.Length == 1 && data[0] == 0x00)//心跳包
|
||||
{
|
||||
//Console.WriteLine("收到心跳包");
|
||||
//无处理
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
HunterNet_C2S _s2c = DeSerizlize<HunterNet_C2S>(data);
|
||||
DataCallBack(sk, (int)_s2c.HunterNetCoreCmdID, _s2c.HunterNetCoreData.ToArray());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("数据解析错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 心跳包时钟事件
|
||||
/// </summary>
|
78
README.md
78
README.md
@ -1,26 +1,88 @@
|
||||
# HaoYueNet
|
||||
|
||||
.Net 7 的,自建基于IOCP的TCP的高性能网络库
|
||||
使用Protobuff作为通讯协议
|
||||
使用Protobuff作为基础协议
|
||||
|
||||
包含服务端和客户端双端库,可直接用于各类.Net程序或Unity程序,做TCP通讯底层库。
|
||||
不用关心网络底层,直接引用或继承,即可便捷使用。
|
||||
|
||||
DataCallBack//网络消息事件
|
||||
OnClose//连接关闭
|
||||
|
||||
并包含心跳包等检测、连接管理、Protobuff解析,优化后的高性能收发等等。
|
||||
|
||||
Simple目录下,有实例客户端和实例服务端,
|
||||
不用关心网络底层,直接引用或继承,即可便捷使用。
|
||||
|
||||
#使用基础事件回调即可:
|
||||
OnClientNumberChange//连接数发生变化
|
||||
OnDisconnected//断开连接
|
||||
OnNetLog//来自网络库的日志信息
|
||||
OnReceive//收到网络数据
|
||||
|
||||
#Simple目录下,有实例客户端和实例服务端
|
||||
示例中,使用本网络库,您可以继续示例项目写,也可以参照示例代码。
|
||||
示例中实现了:
|
||||
|
||||
实现了:
|
||||
|
||||
事件机制,
|
||||
|
||||
客户端基本框架(连接管理,数据管理,消息收发,指定用户发送)
|
||||
|
||||
服务端基本框架(连接管理,用户管理,消息收发,指定用户发送,广播等)
|
||||
|
||||
简单无OAuth登录,
|
||||
|
||||
用户列表,
|
||||
|
||||
基础的Protobuff设计,
|
||||
|
||||
基础聊天功能,
|
||||
|
||||
整合Protobuff生成。
|
||||
|
||||
您甚至可以
|
||||
#最简接入示例(服务端和客户端)
|
||||
若您的应用相对简单,您甚至可以基于Simple增加功能,快速达成目标.
|
||||
|
||||
Server:
|
||||
|
||||
```
|
||||
TcpSaeaServer Srv = new TcpSaeaServer(1024, 1024);//实例化,最大连接数和最大接收字节数
|
||||
Srv.OnClientNumberChange += (int num, AsyncUserToken client) => { /* 连接数发生变化*/};
|
||||
Srv.OnDisconnected += (AsyncUserToken client) => { /* 断开连接 */};
|
||||
Srv.OnNetLog += (string msg) => { /* 来自网络库的日志信息 */};
|
||||
Srv.OnReceive += (AsyncUserToken client, int CMDID, byte[] data) => {
|
||||
/* 收到网络消息 CMDID和数据 */
|
||||
Srv.SendMessage(client, new byte[1] { 0x00 });//给指定连接发送数据
|
||||
};
|
||||
Srv.Init();//初始化
|
||||
Srv.Start(new IPEndPoint(IPAddress.Any.Address, 6000));//启动
|
||||
```
|
||||
|
||||
|
||||
Client:
|
||||
|
||||
```
|
||||
NetworkHelperCore network = new NetworkHelperCore();
|
||||
network.OnClose += ()=> { /* 断开连接 */};
|
||||
network.OnConnected += (bool IsConnect) => { /* 连接回到,成功或失败 */};
|
||||
network.OnLogOut += (string msg) => { /* 来自网络库的日志信息 */};
|
||||
//指定接收服务器数据事件
|
||||
network.OnReceiveData += (int CMDID, int ERRCODE, byte[] data) => {
|
||||
/* 收到网络消息 CMDID和数据 */
|
||||
network.SendToServer(CMDID, new byte[1] { 0x00 });//给服务器发送数据
|
||||
};
|
||||
network.Init("127.0.0.1", 6000);//连接服务器
|
||||
```
|
||||
|
||||
|
||||
#引用姿势
|
||||
|
||||
方式1.直接解决方案引用项目
|
||||
|
||||
方式2.直接引用dll文件
|
||||
|
||||
服务端
|
||||
|
||||
HaoYueNet.ServerNetwork.dll
|
||||
|
||||
客户端
|
||||
|
||||
HaoYueNet.ClientNetwork.dll (.net7 推荐跨平台.net程序使用)
|
||||
|
||||
HaoYueNet.ClientNetworkNet4x.dll (传统.Net4.X版本,用于传统.NetFX程序或Unity游戏,或Mono程序)
|
||||
|
@ -16,15 +16,14 @@ namespace ClientCore.Network
|
||||
public NetworkHelper()
|
||||
{
|
||||
//指定接收服务器数据事件
|
||||
OnDataCallBack += GetDataCallBack;
|
||||
OnReceiveData += GetDataCallBack;
|
||||
//断开连接
|
||||
OnClose += OnConnectClose;
|
||||
//网络库调试信息输出事件,用于打印连接断开,收发事件
|
||||
OnLogOut += NetworkDeBugLog;
|
||||
OnConnected += NetworkConnected;
|
||||
//网络库调试信息输出事件,用于打印网络内容
|
||||
OnLogOut += NetworkDeBugLog;
|
||||
}
|
||||
|
||||
|
||||
public void NetworkConnected(bool IsConnect)
|
||||
{
|
||||
if (IsConnect)
|
||||
|
@ -20,7 +20,6 @@ namespace ServerCore.Manager
|
||||
g_SocketMgr = new IOCPNetWork(1024, 1024);
|
||||
g_SocketMgr.Init();
|
||||
g_SocketMgr.Start(new IPEndPoint(IPAddress.Any.Address, port));
|
||||
Console.WriteLine("监听:" + port);
|
||||
Console.WriteLine("Succeed!");
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,23 @@
|
||||
using AxibugProtobuf;
|
||||
using HaoYueNet.ServerNetwork;
|
||||
using ServerCore.Manager;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace ServerCore.NetWork
|
||||
{
|
||||
public class IOCPNetWork : SocketManager
|
||||
public class IOCPNetWork : TcpSaeaServer
|
||||
{
|
||||
public IOCPNetWork(int numConnections, int receiveBufferSize)
|
||||
: base(numConnections, receiveBufferSize)
|
||||
{
|
||||
ClientNumberChange += IOCPNetWork_ClientNumberChange;
|
||||
OnClientNumberChange += ClientNumberChange;
|
||||
OnReceive += ReceiveData;
|
||||
OnDisconnected += OnDisconnect;
|
||||
OnNetLog += OnShowNetLog;
|
||||
}
|
||||
|
||||
private void IOCPNetWork_ClientNumberChange(int num, AsyncUserToken token)
|
||||
private void ClientNumberChange(int num, AsyncUserToken token)
|
||||
{
|
||||
Console.WriteLine("Client数发生变化");
|
||||
}
|
||||
@ -24,12 +28,12 @@ namespace ServerCore.NetWork
|
||||
/// <param name="CMDID">协议ID</param>
|
||||
/// <param name="ERRCODE">错误编号</param>
|
||||
/// <param name="data">业务数据</param>
|
||||
public override void DataCallBack(AsyncUserToken token, int CMDID, byte[] data)
|
||||
private void ReceiveData(AsyncUserToken token, int CMDID, byte[] data)
|
||||
{
|
||||
DataCallBackToOld(token.Socket, CMDID, data);
|
||||
DataCallBack(token.Socket, CMDID, data);
|
||||
}
|
||||
|
||||
public void DataCallBackToOld(Socket sk, int CMDID, byte[] data)
|
||||
public void DataCallBack(Socket sk, int CMDID, byte[] data)
|
||||
{
|
||||
ServerManager.g_Log.Debug("收到消息 CMDID =>" + CMDID + " 数据长度=>" + data.Length);
|
||||
try
|
||||
@ -47,19 +51,16 @@ namespace ServerCore.NetWork
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
/// <param name="sk"></param>
|
||||
public override void OnClose(AsyncUserToken token)
|
||||
{
|
||||
OnCloseToOld(token.Socket);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
/// <param name="sk"></param>
|
||||
public void OnCloseToOld(Socket sk)
|
||||
public void OnDisconnect(AsyncUserToken token)
|
||||
{
|
||||
Console.WriteLine("断开连接");
|
||||
ServerManager.g_ClientMgr.SetClientOfflineForSocket(sk);
|
||||
ServerManager.g_ClientMgr.SetClientOfflineForSocket(token.Socket);
|
||||
}
|
||||
|
||||
public void OnShowNetLog(string msg)
|
||||
{
|
||||
ServerManager.g_Log.Debug(msg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user