Browse Source

完善事件代码和整理说明

dev_byteoptimize
sin365 11 months ago
parent
commit
dcd4166dc3
  1. BIN
      .vs/HaoYueNet/DesignTimeBuild/.dtbcache.v2
  2. BIN
      .vs/HaoYueNet/FileContentIndex/39bbe2dd-e8e1-4db4-bcfe-eb79f968b5a7.vsidx
  3. BIN
      .vs/HaoYueNet/FileContentIndex/643ee503-1aa5-4aca-9020-1ee57c9825aa.vsidx
  4. BIN
      .vs/HaoYueNet/FileContentIndex/65dc3473-65bb-4667-9cbf-67fd1f6aff3a.vsidx
  5. BIN
      .vs/HaoYueNet/FileContentIndex/968e3c29-ab6c-4352-a325-703532a46e87.vsidx
  6. BIN
      .vs/HaoYueNet/FileContentIndex/9a169cf9-c88b-4c4f-9a0c-d45d55ad2258.vsidx
  7. BIN
      .vs/HaoYueNet/FileContentIndex/b26de889-019d-4af3-b6a2-172ab9c7804b.vsidx
  8. BIN
      .vs/HaoYueNet/FileContentIndex/c4162917-e392-4717-9613-4e8731b5d5a5.vsidx
  9. BIN
      .vs/HaoYueNet/FileContentIndex/cb6d9d57-55ae-4f3d-ad82-1d96865e3b36.vsidx
  10. BIN
      .vs/HaoYueNet/FileContentIndex/cf83e350-4bc5-43f9-81eb-59edbfc5fbf9.vsidx
  11. BIN
      .vs/HaoYueNet/FileContentIndex/e3af48d8-e269-446b-aa11-905c4c1dfd10.vsidx
  12. BIN
      .vs/HaoYueNet/FileContentIndex/e823861b-cc1f-4406-a67a-5aed462afb86.vsidx
  13. BIN
      .vs/HaoYueNet/v17/.futdcache.v2
  14. BIN
      .vs/ProjectEvaluation/haoyuenet.metadata.v5.2
  15. BIN
      .vs/ProjectEvaluation/haoyuenet.projects.v5.2
  16. 38
      NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs
  17. 1
      NetLib/HaoYueNet.ClientNetworkNet4x/HaoYueNet.ClientNetworkNet4x.csproj
  18. 58
      NetLib/HaoYueNet.ClientNetworkNet4x/NetworkHelperCore.cs
  19. 342
      NetLib/HaoYueNet.ServerNetwork/NetWork/TcpSaeaServer.cs
  20. 78
      README.md
  21. 7
      Simple/ClientCore/Network/NetworkHelper.cs
  22. 1
      Simple/ServerCore/Manager/ServerManager.cs
  23. 31
      Simple/ServerCore/NetWork/IOCPNetWork.cs

BIN
.vs/HaoYueNet/DesignTimeBuild/.dtbcache.v2

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/39bbe2dd-e8e1-4db4-bcfe-eb79f968b5a7.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/643ee503-1aa5-4aca-9020-1ee57c9825aa.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/65dc3473-65bb-4667-9cbf-67fd1f6aff3a.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/968e3c29-ab6c-4352-a325-703532a46e87.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/9a169cf9-c88b-4c4f-9a0c-d45d55ad2258.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/b26de889-019d-4af3-b6a2-172ab9c7804b.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/c4162917-e392-4717-9613-4e8731b5d5a5.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/cb6d9d57-55ae-4f3d-ad82-1d96865e3b36.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/cf83e350-4bc5-43f9-81eb-59edbfc5fbf9.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/e3af48d8-e269-446b-aa11-905c4c1dfd10.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/FileContentIndex/e823861b-cc1f-4406-a67a-5aed462afb86.vsidx

Binary file not shown.

BIN
.vs/HaoYueNet/v17/.futdcache.v2

Binary file not shown.

BIN
.vs/ProjectEvaluation/haoyuenet.metadata.v5.2

Binary file not shown.

BIN
.vs/ProjectEvaluation/haoyuenet.projects.v5.2

Binary file not shown.

38
NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs

@ -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()

1
NetLib/HaoYueNet.ClientNetworkNet4x/HaoYueNet.ClientNetworkNet4x.csproj

@ -59,6 +59,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="NetworkHelperCore.cs" />
<Compile Include="NetworkHelperP2PCore.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ProtobufHunterNetCore.cs" />
</ItemGroup>

58
NetLib/HaoYueNet.ClientNetworkNet4x/NetworkHelperCore.cs

@ -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;
}
}
}
}

342
NetLib/HaoYueNet.ServerNetwork/NetWork/SocketManager.cs → NetLib/HaoYueNet.ServerNetwork/NetWork/TcpSaeaServer.cs

@ -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;
//调用关闭连接
OnClose(token);
RemoveUserToken(token);
// determine which type of operation just completed and call the associated handler
//如果有事件,则调用事件,发送客户端数量变化通知
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)
{
}
/// <summary>
/// 断开连接
/// </summary>
/// <param name="sk"></param>
public virtual void OnClose(AsyncUserToken sk)
{
}
public virtual void OnCloseReady(AsyncUserToken token)
private 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,27 +632,6 @@ namespace HaoYueNet.ServerNetwork
SendWithIndex(token, _finaldata);
}
/// <summary>
/// 发送心跳包
/// </summary>
/// <param name="sk"></param>
///
private void SendHeartbeat(AsyncUserToken token)
{
if (token == null || token.Socket == null || !token.Socket.Connected)
return;
try
{
//Console.WriteLine(DateTime.Now.ToString() + "发送心跳包");
token.SendIndex = MaxSendIndexNum;
SendMessage(token, HeartbeatData, true);
}
catch (Exception e)
{
OnCloseReady(token);
}
}
private void DataCallBackReady(AsyncUserToken sk, byte[] data)
{
//增加接收计数
@ -677,7 +639,7 @@ namespace HaoYueNet.ServerNetwork
if (data.Length == 1 && data[0] == 0x00)//心跳包
{
//Console.WriteLine("收到心跳包");
//OutNetLog("收到心跳包");
//无处理
}
else
@ -685,15 +647,45 @@ namespace HaoYueNet.ServerNetwork
try
{
HunterNet_C2S _s2c = DeSerizlize<HunterNet_C2S>(data);
DataCallBack(sk, (int)_s2c.HunterNetCoreCmdID, _s2c.HunterNetCoreData.ToArray());
//将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度.
OnReceive?.Invoke(sk, (int)_s2c.HunterNetCoreCmdID, _s2c.HunterNetCoreData.ToArray());
//DataCallBack(sk, (int)_s2c.HunterNetCoreCmdID, _s2c.HunterNetCoreData.ToArray());
}
catch (Exception ex)
{
Console.WriteLine("数据解析错误");
OutNetLog("数据解析错误");
}
}
}
private void OutNetLog(string msg)
{
OnNetLog?.Invoke(msg);
}
#endregion
#region 心跳包
/// <summary>
/// 发送心跳包
/// </summary>
/// <param name="sk"></param>
///
private void SendHeartbeat(AsyncUserToken token)
{
if (token == null || token.Socket == null || !token.Socket.Connected)
return;
try
{
//OutNetLog(DateTime.Now.ToString() + "发送心跳包");
token.SendIndex = MaxSendIndexNum;
SendMessage(token, HeartbeatData, true);
}
catch (Exception e)
{
OnCloseReady(token);
}
}
/// <summary>
/// 心跳包时钟事件
/// </summary>

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程序)

7
Simple/ClientCore/Network/NetworkHelper.cs

@ -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)

1
Simple/ServerCore/Manager/ServerManager.cs

@ -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!");
}
}

31
Simple/ServerCore/NetWork/IOCPNetWork.cs

@ -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)
public void OnDisconnect(AsyncUserToken token)
{
OnCloseToOld(token.Socket);
Console.WriteLine("断开连接");
ServerManager.g_ClientMgr.SetClientOfflineForSocket(token.Socket);
}
/// <summary>
/// 断开连接
/// </summary>
/// <param name="sk"></param>
public void OnCloseToOld(Socket sk)
public void OnShowNetLog(string msg)
{
Console.WriteLine("断开连接");
ServerManager.g_ClientMgr.SetClientOfflineForSocket(sk);
ServerManager.g_Log.Debug(msg);
}
}
}

Loading…
Cancel
Save