mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-11-11 00:36:00 +00:00
提交Unity 联机Pro
This commit is contained in:
3
JNFrame2/Assets/JNGame/Network/Action.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Action.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd0b2e123a2647faa14dc3c101cb9924
|
||||
timeCreated: 1706264437
|
||||
34
JNFrame2/Assets/JNGame/Network/Action/NActionEnum.cs
Normal file
34
JNFrame2/Assets/JNGame/Network/Action/NActionEnum.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
namespace Plugins.JNGame.Network.Action
|
||||
{
|
||||
public enum NActionEnum : int
|
||||
{
|
||||
Ping = 1, //PING
|
||||
NActionDemo = 2, //Demo 消息
|
||||
NActionDemo2 = 3, //Demo 消息
|
||||
|
||||
ClientConnect = 11, //客户端连接
|
||||
ClientDisconnect = 12, //客户端断开
|
||||
|
||||
NSyncFrameStart = 100, //帧同步开始
|
||||
NSyncFrameEnd = 101, //帧同步结束
|
||||
NSyncFrameBack = 102, //帧同步回调
|
||||
NSyncFrameInput = 103, //帧同步输入
|
||||
NSyncFrameReset = 104, //重置帧同步
|
||||
|
||||
NSyncStateStartRequest = 110, //状态同步开始
|
||||
NSyncStateEndRequest = 111, //状态同步结束
|
||||
NSyncStateBackResponse = 112, //状态同步回调
|
||||
NSyncStateDataUpdateRequest = 113, //状态同步更新
|
||||
NSyncStateAllUpdateRequest = 114, //状态全量更新
|
||||
NSyncStateAllBackResponse = 115, //状态同步全量回调
|
||||
|
||||
NSyncStateDataUpdate = 121, //状态同步更新
|
||||
NSyncStateAllUpdate = 122, //状态全量更新
|
||||
NSyncStateAllBack = 123, //状态同步全量回调
|
||||
|
||||
NSyncTileInput = 131, //状态Tile同步输入
|
||||
|
||||
NAddTileServer = 141, //添加区块服务器
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07d3dc0f03a24e18b4bee8832eef7a47
|
||||
timeCreated: 1706264441
|
||||
8
JNFrame2/Assets/JNGame/Network/Entity.meta
Normal file
8
JNFrame2/Assets/JNGame/Network/Entity.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d3cabfc01539db4dbf0d4961f07368c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
48
JNFrame2/Assets/JNGame/Network/Entity/JNetParam.cs
Normal file
48
JNFrame2/Assets/JNGame/Network/Entity/JNetParam.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace Plugins.JNGame.Network.Entity
|
||||
{
|
||||
public class JNetParam
|
||||
{
|
||||
|
||||
//请求处理 Id (用来找到处理方法)
|
||||
private int _hId;
|
||||
public int HId => _hId;
|
||||
|
||||
//请求Id (请求标识)
|
||||
private int _id;
|
||||
public int ID => _id;
|
||||
|
||||
|
||||
//请求参数
|
||||
private IMessage _data;
|
||||
public IMessage Data => _data;
|
||||
|
||||
|
||||
private byte[] _bytes;
|
||||
|
||||
public byte[] Bytes => _bytes;
|
||||
|
||||
public JNetParam(int id,int hId)
|
||||
{
|
||||
_hId = hId;
|
||||
_id = id;
|
||||
}
|
||||
|
||||
//构造器
|
||||
public static JNetParam Build(int id,int hId){
|
||||
return new JNetParam(id,hId);
|
||||
}
|
||||
|
||||
|
||||
public JNetParam SetData(IMessage data){
|
||||
this._data = data;
|
||||
return this;
|
||||
}
|
||||
public JNetParam SetByte(byte[] bytes){
|
||||
this._bytes = bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/Entity/JNetParam.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Entity/JNetParam.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f311c8c368584fab839dd72819fc55da
|
||||
timeCreated: 1706004134
|
||||
3
JNFrame2/Assets/JNGame/Network/Group.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Group.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 991b566ca2e345839d3047cb0a0870c9
|
||||
timeCreated: 1723169977
|
||||
76
JNFrame2/Assets/JNGame/Network/Group/JNClientGroup.cs
Normal file
76
JNFrame2/Assets/JNGame/Network/Group/JNClientGroup.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Google.Protobuf;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
using Plugins.JNGame.System;
|
||||
using Plugins.JNGame.Util;
|
||||
|
||||
namespace Plugins.JNGame.Network.Group
|
||||
{
|
||||
public class JNClientGroup<T> : SystemBase where T : JNClientBase
|
||||
{
|
||||
|
||||
//创建通知
|
||||
protected EventDispatcher _event = new();
|
||||
//客户端组
|
||||
public List<T> group = new List<T>();
|
||||
|
||||
|
||||
public override async Task OnInit()
|
||||
{
|
||||
await UniTask.NextFrame();
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
base.OnClose();
|
||||
foreach (var client in group)
|
||||
{
|
||||
client.OnClose();
|
||||
}
|
||||
group.Clear();
|
||||
}
|
||||
|
||||
public virtual void AddClient(T client)
|
||||
{
|
||||
group.Add(client);
|
||||
client.SetEvent(_event);
|
||||
client.OnInit();
|
||||
}
|
||||
|
||||
public virtual void RemoveClient(T client)
|
||||
{
|
||||
client.SetEvent(new EventDispatcher());
|
||||
client.OnClose();
|
||||
group.Remove(client);
|
||||
}
|
||||
|
||||
//外部监听消息
|
||||
public void AddListener(int hId,Action<byte[]> listener)
|
||||
{
|
||||
_event.AddListener($"{hId}",listener);
|
||||
}
|
||||
|
||||
//删除外部监听
|
||||
public void RemoveListener(int hId,Action<byte[]> listener)
|
||||
{
|
||||
_event.RemoveListener($"{hId}",listener);
|
||||
}
|
||||
|
||||
//向服务器发送消息
|
||||
public void Send(int hId,IMessage data = null,Func<T,bool> filter = null)
|
||||
{
|
||||
filter ??= (T client) => true;
|
||||
group.ForEach(child =>
|
||||
{
|
||||
if (filter(child))
|
||||
{
|
||||
child.Send(hId,data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 285c1ebc46554e9aa51b6831fc09a650
|
||||
timeCreated: 1723170178
|
||||
81
JNFrame2/Assets/JNGame/Network/JNClientBase.cs
Normal file
81
JNFrame2/Assets/JNGame/Network/JNClientBase.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using AppGame;
|
||||
using DotRecast.Core.Collections;
|
||||
using Google.Protobuf;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
using Plugins.JNGame.System;
|
||||
using Plugins.JNGame.Util;
|
||||
|
||||
namespace Plugins.JNGame.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础客户端网络类
|
||||
/// </summary>
|
||||
public abstract class JNClientBase : SystemBase
|
||||
{
|
||||
|
||||
//消息Id
|
||||
protected int _id = 0;
|
||||
|
||||
//创建通知
|
||||
protected EventDispatcher _event = new();
|
||||
|
||||
//计入字节大小
|
||||
protected Dictionary<int, int> _byteSize = new();
|
||||
|
||||
public void SetEvent(EventDispatcher dispatcher)
|
||||
{
|
||||
_event = dispatcher;
|
||||
}
|
||||
//外部监听消息
|
||||
public void AddListener(int hId,Action<byte[]> listener)
|
||||
{
|
||||
_event.AddListener($"{hId}",listener);
|
||||
}
|
||||
//删除外部监听
|
||||
public void RemoveListener(int hId,Action<byte[]> listener)
|
||||
{
|
||||
_event.RemoveListener($"{hId}",listener);
|
||||
}
|
||||
|
||||
//通知消息
|
||||
public virtual void Dispatch(JNetParam data)
|
||||
{
|
||||
_byteSize[data.HId] = data.Bytes.Length;
|
||||
//发送消息
|
||||
_event.Dispatch($"{data.HId}",data.Bytes);
|
||||
}
|
||||
|
||||
//向服务器发送消息
|
||||
public virtual void Send(int hId,IMessage data = null)
|
||||
{
|
||||
var bytes = NDataUtil.Encrypt(JNetParam.Build(this._id++, hId).SetData(data));
|
||||
_byteSize[hId] = bytes.Length;
|
||||
SendBytes(bytes);
|
||||
}
|
||||
|
||||
public virtual void SendBytes(byte[] data){ }
|
||||
|
||||
public abstract Task StartConnect();
|
||||
|
||||
//获取字节大小
|
||||
public int GetByteSize(int hId = 0)
|
||||
{
|
||||
if (hId == 0)
|
||||
{
|
||||
int size = 0;
|
||||
_byteSize.ForEach(child =>
|
||||
{
|
||||
size += child.Value;
|
||||
});
|
||||
return size;
|
||||
}
|
||||
return _byteSize.GetValueOrDefault(hId, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/JNClientBase.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/JNClientBase.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fd9f54f293b4a56834c2eb1297eeb25
|
||||
timeCreated: 1722411861
|
||||
84
JNFrame2/Assets/JNGame/Network/JNServerBase.cs
Normal file
84
JNFrame2/Assets/JNGame/Network/JNServerBase.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using DotRecast.Core.Collections;
|
||||
using Google.Protobuf;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
using Plugins.JNGame.System;
|
||||
using Plugins.JNGame.Util;
|
||||
|
||||
namespace Plugins.JNGame.Network
|
||||
{
|
||||
|
||||
public class JNServerParam
|
||||
{
|
||||
|
||||
public int Client;
|
||||
|
||||
public byte[] Message;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基础服务端网络类
|
||||
/// </summary>
|
||||
public abstract class JNServerBase : SystemBase
|
||||
{
|
||||
//消息Id
|
||||
protected int _id = 0;
|
||||
|
||||
//创建通知
|
||||
protected EventDispatcher _event = new();
|
||||
|
||||
//计入字节大小
|
||||
protected Dictionary<int, int> _byteSize = new();
|
||||
|
||||
/// <summary>
|
||||
/// 监听服务端事件
|
||||
/// </summary>
|
||||
/// <param name="hId"></param>
|
||||
/// <param name="listener"></param>
|
||||
public void AddListener(int hId,Action<JNServerParam> listener)
|
||||
{
|
||||
_event.AddListener($"{hId}",listener);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送消息
|
||||
/// </summary>
|
||||
/// <param name="hId"></param>
|
||||
/// <param name="data"></param>
|
||||
public void Dispatch(int hId,JNServerParam data)
|
||||
{
|
||||
_event.Dispatch($"{hId}",data);
|
||||
}
|
||||
|
||||
//获取字节大小
|
||||
public int GetByteSize(int hId = 0)
|
||||
{
|
||||
if (hId == 0)
|
||||
{
|
||||
int size = 0;
|
||||
try
|
||||
{
|
||||
_byteSize.ForEach(child =>
|
||||
{
|
||||
size += child.Value;
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
return _byteSize.GetValueOrDefault(hId, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/JNServerBase.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/JNServerBase.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e9eb4fd951a46468c406606ec2107bd
|
||||
timeCreated: 1722413222
|
||||
87
JNFrame2/Assets/JNGame/Network/JNSocket.cs
Normal file
87
JNFrame2/Assets/JNGame/Network/JNSocket.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BestHTTP.WebSocket;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DotRecast.Core.Collections;
|
||||
using Google.Protobuf;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
using Plugins.JNGame.Util;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Plugins.JNGame.Network
|
||||
{
|
||||
public abstract class JNSocket : JNClientBase
|
||||
{
|
||||
|
||||
private WebSocket _socket;
|
||||
|
||||
private UniTaskCompletionSource _onOpen;
|
||||
|
||||
|
||||
public override async Task OnInit()
|
||||
{
|
||||
await StartConnect();
|
||||
}
|
||||
|
||||
public override async Task StartConnect()
|
||||
{
|
||||
|
||||
var url = $"{await this.GetUrl()}";
|
||||
this._socket = new WebSocket(new Uri(url));
|
||||
|
||||
this._socket.OnOpen += OnOpen;
|
||||
this._socket.OnMessage += OnMessageReceived;
|
||||
this._socket.OnError += OnError;
|
||||
this._socket.OnClosed += OnClosed;
|
||||
this._socket.OnBinary += Onbinary;
|
||||
|
||||
Debug.Log($"[JNSocket]初始化WebSocket成功,URL:{url}");
|
||||
this._socket.Open();
|
||||
|
||||
//等待连接成功
|
||||
await (this._onOpen = new UniTaskCompletionSource()).Task;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void OnOpen(WebSocket websocket)
|
||||
{
|
||||
Debug.Log($"[JNSocket] OnOpen");
|
||||
this._onOpen.TrySetResult();
|
||||
}
|
||||
|
||||
private void OnMessageReceived(WebSocket websocket, string message)
|
||||
{
|
||||
Debug.Log($"[JNSocket] OnMessageReceived");
|
||||
}
|
||||
|
||||
private void OnError(WebSocket websocket, string reason)
|
||||
{
|
||||
Debug.Log($"[JNSocket] OnError");
|
||||
}
|
||||
|
||||
private void OnClosed(WebSocket websocket, ushort code, string message)
|
||||
{
|
||||
Debug.Log($"[JNSocket] OnClosed");
|
||||
}
|
||||
|
||||
private void Onbinary(WebSocket websocket, byte[] data)
|
||||
{
|
||||
|
||||
// NSystem.Log($"[JNSocket] Onbinary");
|
||||
Dispatch(NDataUtil.Parse(data));
|
||||
|
||||
}
|
||||
|
||||
protected abstract UniTask<string> GetUrl();
|
||||
|
||||
public override void SendBytes(byte[] data)
|
||||
{
|
||||
_socket.Send(data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
JNFrame2/Assets/JNGame/Network/JNSocket.cs.meta
Normal file
11
JNFrame2/Assets/JNGame/Network/JNSocket.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85daeb9010873c6408e58fd210d7ec47
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
97
JNFrame2/Assets/JNGame/Network/JNTCPClient.cs
Normal file
97
JNFrame2/Assets/JNGame/Network/JNTCPClient.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DotNetty.Transport.Bootstrapping;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Sockets;
|
||||
using Google.Protobuf;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using TestNetty.Client.Initializers;
|
||||
using UnityEngine;
|
||||
using NotImplementedException = System.NotImplementedException;
|
||||
|
||||
namespace Plugins.JNGame.Network
|
||||
{
|
||||
public class JNTCPClient : JNClientBase
|
||||
{
|
||||
|
||||
private IChannel clientChannel;
|
||||
private IEventLoopGroup group;
|
||||
private Bootstrap bootstrap;
|
||||
|
||||
public bool IsOpen => clientChannel is not null && clientChannel.Open;
|
||||
|
||||
public override async Task OnInit()
|
||||
{
|
||||
|
||||
await base.OnInit();
|
||||
|
||||
await StartConnect();
|
||||
|
||||
}
|
||||
|
||||
public override async Task StartConnect()
|
||||
{
|
||||
|
||||
if (!isStart) return;
|
||||
await CloseNetty();
|
||||
|
||||
group = new MultithreadEventLoopGroup();
|
||||
bootstrap = new Bootstrap();
|
||||
bootstrap
|
||||
.Group(group)
|
||||
.Channel<TcpSocketChannel>()
|
||||
.Option(ChannelOption.TcpNodelay, true)
|
||||
.Handler(new TcpClientInitializer(this));
|
||||
|
||||
try
|
||||
{
|
||||
if (bootstrap is not null)
|
||||
{
|
||||
Debug.Log($"[JNTCPClient] 开始连接");
|
||||
clientChannel = await bootstrap.ConnectAsync( await GetEndPoint() );
|
||||
Debug.Log($"[JNTCPClient] 连接成功");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning(e.Message);
|
||||
Debug.Log($"[JNTCPClient] 连接失败 1s后重试");
|
||||
await UniTask.DelayFrame(1000);
|
||||
await StartConnect();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async UniTask<IPEndPoint> GetEndPoint()
|
||||
{
|
||||
await UniTask.NextFrame();
|
||||
return new IPEndPoint(IPAddress.Parse("127.0.0.1"),9001);
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
base.OnClose();
|
||||
CloseNetty();
|
||||
}
|
||||
|
||||
private async Task CloseNetty()
|
||||
{
|
||||
clientChannel?.CloseAsync();
|
||||
if (group is not null) await group.ShutdownGracefullyAsync();
|
||||
group = null;
|
||||
clientChannel = null;
|
||||
bootstrap = null;
|
||||
}
|
||||
|
||||
public override void Send(int hId, IMessage data = null)
|
||||
{
|
||||
base.Send(hId, data);
|
||||
if (IsOpen)
|
||||
{
|
||||
// clientChannel?.WriteAndFlushAsync(JNetParam.Build(this._id++, hId).SetData(data));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/JNTCPClient.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/JNTCPClient.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fd761856d3b4ea397624b0de69911e9
|
||||
timeCreated: 1722409435
|
||||
105
JNFrame2/Assets/JNGame/Network/JNTCPServer.cs
Normal file
105
JNFrame2/Assets/JNGame/Network/JNTCPServer.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Transport.Bootstrapping;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Sockets;
|
||||
using DotRecast.Core.Collections;
|
||||
using Google.Protobuf;
|
||||
using JNGame.Network.Netty.TCP;
|
||||
using Plugins.JNGame.Network;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace JNGame.Network
|
||||
{
|
||||
public class JNTCPServer : JNServerBase
|
||||
{
|
||||
|
||||
private int _port = 0;
|
||||
public int Port => _port;
|
||||
|
||||
private ServerBootstrap bootstrap;
|
||||
private IEventLoopGroup bossGroup;
|
||||
private IEventLoopGroup workerGroup;
|
||||
private IChannel channel;
|
||||
|
||||
private TcpServerInitializer server;
|
||||
|
||||
public override async Task OnInit()
|
||||
{
|
||||
|
||||
bossGroup = new MultithreadEventLoopGroup(1);
|
||||
workerGroup = new MultithreadEventLoopGroup(4);
|
||||
bootstrap = new ServerBootstrap();
|
||||
bootstrap.Group(bossGroup, workerGroup);
|
||||
bootstrap.Channel<TcpServerSocketChannel>();
|
||||
bootstrap
|
||||
.Option(ChannelOption.SoBacklog, 1024)
|
||||
//ByteBuf的分配器(重用缓冲区)大小
|
||||
.Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)
|
||||
.Option(ChannelOption.RcvbufAllocator, new FixedRecvByteBufAllocator(1024 * 8))
|
||||
.ChildOption(ChannelOption.SoKeepalive, true) //保持长连接
|
||||
.ChildOption(ChannelOption.TcpNodelay, true) //端口复用
|
||||
.ChildOption(ChannelOption.SoReuseport, true)
|
||||
//自定义初始化Tcp服务
|
||||
.ChildHandler(server = new TcpServerInitializer(this));
|
||||
|
||||
await StartBind();
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected async Task StartBind()
|
||||
{
|
||||
try
|
||||
{
|
||||
channel = await bootstrap.BindAsync(_port = await GetPort());
|
||||
Debug.Log($"[JNTCPServer] 服务器创建成功");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning(e.Message);
|
||||
Debug.Log($"[JNTCPServer] 服务器创建失败 1s后重试");
|
||||
await UniTask.DelayFrame(1000);
|
||||
await StartBind();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async UniTask<int> GetPort()
|
||||
{
|
||||
await UniTask.NextFrame();
|
||||
return 9001;
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
base.OnClose();
|
||||
CloseNetty();
|
||||
Debug.Log($"[JNTCPServer] 关闭连接");
|
||||
|
||||
}
|
||||
|
||||
private async Task CloseNetty()
|
||||
{
|
||||
channel?.CloseAsync();
|
||||
bossGroup?.ShutdownGracefullyAsync();
|
||||
workerGroup?.ShutdownGracefullyAsync();
|
||||
channel = null;
|
||||
bossGroup = null;
|
||||
workerGroup = null;
|
||||
}
|
||||
|
||||
public void AllSend(int hId,IMessage data = null)
|
||||
{
|
||||
server.GetClients().ForEach(id => Send(id,hId,data));
|
||||
}
|
||||
|
||||
public void Send(int client,int hId,IMessage data = null)
|
||||
{
|
||||
IChannelHandlerContext context = server.GetClient(client);
|
||||
context.WriteAsync(JNetParam.Build(this._id++, hId).SetData(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/JNTCPServer.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/JNTCPServer.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ec8c583ae4a4a8686002cec976893b0
|
||||
timeCreated: 1722409447
|
||||
107
JNFrame2/Assets/JNGame/Network/JNUDPClient.cs
Normal file
107
JNFrame2/Assets/JNGame/Network/JNUDPClient.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using JNGame.Util;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
using UnityEngine;
|
||||
using NotImplementedException = System.NotImplementedException;
|
||||
|
||||
namespace Plugins.JNGame.Network
|
||||
{
|
||||
public abstract class JNTCPClient1 : JNClientBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 客户端
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Socket client;
|
||||
|
||||
/// <summary>
|
||||
/// 客户端线程
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Thread thread;
|
||||
|
||||
/// <summary>
|
||||
/// 是否连接
|
||||
/// </summary>
|
||||
public bool isConnect { get; private set; }
|
||||
|
||||
private Queue<byte[]> cache = new ();
|
||||
|
||||
public override async Task OnInit()
|
||||
{
|
||||
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
client.Connect(await GetEndPoint());
|
||||
thread = new Thread(CreatConnectSocket);
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
Debug.Log($"[JNTCPClient] 关闭客户端");
|
||||
base.OnClose();
|
||||
client?.Close();
|
||||
thread?.Abort();
|
||||
}
|
||||
|
||||
protected virtual async UniTask<IPEndPoint> GetEndPoint()
|
||||
{
|
||||
await UniTask.NextFrame();
|
||||
return new IPEndPoint(IPAddress.Parse("127.0.0.1"),9001);
|
||||
}
|
||||
|
||||
private void CreatConnectSocket()
|
||||
{
|
||||
Debug.Log($"[JNTCPClient] 连接服务器成功");
|
||||
isConnect = true;
|
||||
PushCache();
|
||||
byte[] bytes = new byte[102400];
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var max = client.Receive(bytes);
|
||||
var message = new byte[max];
|
||||
Array.Copy(bytes, message, max);
|
||||
var param = NDataUtil.Parse(message);
|
||||
Dispatch(param);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// ignored
|
||||
Debug.LogWarning(e.Message);
|
||||
Debug.Log($"[JNTCPClient] 断开连接");
|
||||
isConnect = false;
|
||||
client.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SendBytes(byte[] data)
|
||||
{
|
||||
if (data is null || data.Length <= 0) return;
|
||||
cache.Enqueue(data);
|
||||
if (isConnect)
|
||||
{
|
||||
PushCache();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送缓存
|
||||
/// </summary>
|
||||
public void PushCache()
|
||||
{
|
||||
while (isConnect && cache.TryDequeue(out var bytes))
|
||||
{
|
||||
NetTool.SendAsync(client,bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/JNUDPClient.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/JNUDPClient.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cd63835ebd243888fb11eb3fb168a92
|
||||
timeCreated: 1723799588
|
||||
172
JNFrame2/Assets/JNGame/Network/JNUDPServer.cs
Normal file
172
JNFrame2/Assets/JNGame/Network/JNUDPServer.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DotRecast.Core.Collections;
|
||||
using Google.Protobuf;
|
||||
using JNGame.Util.Types;
|
||||
using Plugins.JNGame.Network.Action;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
using Plugins.JNGame.System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Plugins.JNGame.Network
|
||||
{
|
||||
public abstract class JNTCPServer1 : JNServerBase
|
||||
{
|
||||
|
||||
// /// <summary>
|
||||
// /// 服务器
|
||||
// /// </summary>
|
||||
// /// <returns></returns>
|
||||
// private TcpListener server;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 服务器线程
|
||||
// /// </summary>
|
||||
// /// <returns></returns>
|
||||
// private Thread thread;
|
||||
// /// <summary>
|
||||
// /// 客户端线程
|
||||
// /// </summary>
|
||||
// /// <returns></returns>
|
||||
// private Dictionary<string,Socket> threads = new();
|
||||
//
|
||||
// private int _clientIndex = 0;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 连接的客户端
|
||||
// /// </summary>
|
||||
// KeyValue<int,Socket> clients = new ();
|
||||
//
|
||||
// private int _port = 0;
|
||||
// public int Port => _port;
|
||||
//
|
||||
//
|
||||
// public override async Task OnInit()
|
||||
// {
|
||||
// await CreateServer();
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 关闭服务器
|
||||
// /// </summary>
|
||||
// public override void OnClose()
|
||||
// {
|
||||
// Debug.Log($"[JNUDPServer] 关闭服务器");
|
||||
// base.OnClose();
|
||||
// server?.Stop();
|
||||
// thread?.Abort();
|
||||
// threads.ForEach(child => child.Value.Close());
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 创建服务器
|
||||
// /// </summary>
|
||||
// private async UniTask CreateServer()
|
||||
// {
|
||||
//
|
||||
// server = new TcpListener(IPAddress.Any,_port = await GetPort());
|
||||
// server.Start();
|
||||
// thread = new Thread(CreatConnectSocket);
|
||||
// thread.Start();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// protected virtual async UniTask<int> GetPort()
|
||||
// {
|
||||
// await UniTask.NextFrame();
|
||||
// return 9001;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 接受监听后保存生成的通信客户端,并开启线程监听通信客户端消息
|
||||
// /// </summary>
|
||||
// void CreatConnectSocket()
|
||||
// {
|
||||
// Debug.Log($"[JNTCPServer] 创建服务器成功");
|
||||
// while (true)
|
||||
// {
|
||||
// _clientIndex += 1;
|
||||
// Socket socket = server.AcceptSocket();
|
||||
// clients.Add(_clientIndex,socket);
|
||||
// Thread thread1 = new Thread(() => { ListenConnectSocket(socket); });
|
||||
// thread1.Start();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 接受通信客户端消息并对消息进行处理
|
||||
// /// </summary>
|
||||
// /// <param name="socket"></param>
|
||||
// void ListenConnectSocket(Socket socket)
|
||||
// {
|
||||
// Debug.Log($"[JNTCPServer] 客户端连接");
|
||||
// //客户端连接
|
||||
// _event.Dispatch($"{(int)NActionEnum.ClientConnect}",new JNServerParam()
|
||||
// {
|
||||
// Client = socket,
|
||||
// Message = Array.Empty<byte>()
|
||||
// });
|
||||
// byte[] bytes = new byte[102400];
|
||||
// try
|
||||
// {
|
||||
// while (true)
|
||||
// {
|
||||
// var max = socket.Receive(bytes);
|
||||
// var message = new byte[max];
|
||||
// if (max >= 102400)
|
||||
// {
|
||||
// throw new Exception($"[JNTCPServer] 超出最大接收{max}");
|
||||
// }
|
||||
// Array.Copy(bytes,message,max);
|
||||
// var param = NDataUtil.Parse(message);
|
||||
// _byteSize[param.HId] = param.Bytes.Length;
|
||||
// _event.Dispatch($"{param.HId}",new JNServerParam()
|
||||
// {
|
||||
// Client = socket,
|
||||
// Message = param.Bytes
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Debug.LogWarning(e.Message);
|
||||
// Debug.Log($"[JNTCPServer] 断开客户端连接");
|
||||
// //客户端断开
|
||||
// _event.Dispatch($"{(int)NActionEnum.ClientDisconnect}",new JNServerParam()
|
||||
// {
|
||||
// Client = socket,
|
||||
// Message = Array.Empty<byte>()
|
||||
// });
|
||||
// socket.Close();
|
||||
// clients.RemoveByValue(socket);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void Send(Socket client,int hId,IMessage data = null)
|
||||
// {
|
||||
// var bytes = NDataUtil.Encrypt(JNetParam.Build(this._id++, hId).SetData(data));
|
||||
// _byteSize[hId] = bytes.Length;
|
||||
// client.SendAsync(bytes,SocketFlags.None);
|
||||
// }
|
||||
//
|
||||
// public void AllSend(int hId,IMessage data = null)
|
||||
// {
|
||||
// clients.Values.ForEach(child =>
|
||||
// {
|
||||
// Send(child.Value, hId, data);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
public override Task OnInit()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/JNUDPServer.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/JNUDPServer.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0133b6e17024e67a3e0c86689c7ba9b
|
||||
timeCreated: 1723725100
|
||||
3
JNFrame2/Assets/JNGame/Network/Netty.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Netty.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5da486bbb35a4830bbf04c02e4d64dae
|
||||
timeCreated: 1723773802
|
||||
34
JNFrame2/Assets/JNGame/Network/Netty/HeartBeatHandler.cs
Normal file
34
JNFrame2/Assets/JNGame/Network/Netty/HeartBeatHandler.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using DotNetty.Handlers.Timeout;
|
||||
using DotNetty.Transport.Channels;
|
||||
|
||||
namespace JNGame.Network.Netty
|
||||
{
|
||||
/// <summary>
|
||||
/// Heartbeat Handler Class.
|
||||
/// </summary>
|
||||
public class HeartBeatHandler : ChannelHandlerAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Heart Beat Handler.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="evt"></param>
|
||||
public override void UserEventTriggered(IChannelHandlerContext context, object evt)
|
||||
{
|
||||
var eventState = evt as IdleStateEvent;
|
||||
if (eventState != null)
|
||||
{
|
||||
if (eventState.State == IdleState.ReaderIdle)
|
||||
{
|
||||
context.Channel.Flush();
|
||||
context.Channel.CloseAsync();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.UserEventTriggered(context, evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 428846a1397f4426b81f1b79876325ef
|
||||
timeCreated: 1723775429
|
||||
3
JNFrame2/Assets/JNGame/Network/Netty/TCP.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Netty/TCP.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b093de57a09748848035e479d1248ea4
|
||||
timeCreated: 1723773808
|
||||
111
JNFrame2/Assets/JNGame/Network/Netty/TCP/TcpClientHandler.cs
Normal file
111
JNFrame2/Assets/JNGame/Network/Netty/TCP/TcpClientHandler.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Transport.Channels;
|
||||
using JNGame.Util.Types;
|
||||
using Plugins.JNGame.Network;
|
||||
using Plugins.JNGame.Network.Action;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace JNGame.Network.Netty.TCP
|
||||
{
|
||||
public class TcpClientHandler : ChannelHandlerAdapter
|
||||
{
|
||||
|
||||
private JNClientBase root;
|
||||
|
||||
public TcpClientHandler(JNClientBase client)
|
||||
{
|
||||
root = client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逻辑处理器被添加
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void HandlerAdded(IChannelHandlerContext context)
|
||||
{
|
||||
base.HandlerAdded(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绑定到线程
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelRegistered(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelRegistered(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 准备就绪
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelActive(IChannelHandlerContext context)
|
||||
{
|
||||
|
||||
base.ChannelActive(context);
|
||||
Debug.Log($"[TcpClientHandler] 连接成功: {context.Channel.RemoteAddress}");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 有数据可读
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="message"></param>
|
||||
public override void ChannelRead(IChannelHandlerContext context, object message)
|
||||
{
|
||||
|
||||
base.ChannelRead(context, message);
|
||||
|
||||
if (message is not JNetParam data) return;
|
||||
|
||||
root.Dispatch(data);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 某次数据读完
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelReadComplete(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelReadComplete(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 被关闭
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelInactive(IChannelHandlerContext context)
|
||||
{
|
||||
|
||||
base.ChannelInactive(context);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消线程(NioEventLoop) 的绑定
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelUnregistered(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelUnregistered(context);
|
||||
context.Channel.EventLoop.Schedule(() =>
|
||||
{
|
||||
Debug.Log($"重连接: {context.Channel.RemoteAddress}");
|
||||
root.StartConnect();
|
||||
}, new TimeSpan(1000));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逻辑处理器被移除
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void HandlerRemoved(IChannelHandlerContext context)
|
||||
{
|
||||
base.HandlerRemoved(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a6cf562019b4e4eaf5fae1b4bb2b19f
|
||||
timeCreated: 1723799944
|
||||
@@ -0,0 +1,34 @@
|
||||
using DotNetty.Handlers.Logging;
|
||||
using DotNetty.Handlers.Timeout;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Sockets;
|
||||
using JNGame.Network.Netty;
|
||||
using JNGame.Network.Netty.TCP;
|
||||
using Plugins.JNGame.Network;
|
||||
using TestNetty.Service.Handlers;
|
||||
|
||||
namespace TestNetty.Client.Initializers
|
||||
{
|
||||
public class TcpClientInitializer : ChannelInitializer<ISocketChannel>
|
||||
{
|
||||
|
||||
private JNClientBase root;
|
||||
private TcpClientHandler handler;
|
||||
|
||||
public TcpClientInitializer(JNClientBase server)
|
||||
{
|
||||
root = server;
|
||||
handler = new TcpClientHandler(root);
|
||||
}
|
||||
|
||||
protected override void InitChannel(ISocketChannel channel)
|
||||
{
|
||||
IChannelPipeline pipeline = channel.Pipeline;
|
||||
pipeline.AddLast(new IdleStateHandler(30, 30, 60 * 5));
|
||||
pipeline.AddLast(new HeartBeatHandler());
|
||||
pipeline.AddLast("encoder", new TcpEncoderHandler());
|
||||
pipeline.AddLast("decoder", new TcpDecoderHandler());
|
||||
pipeline.AddLast(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96db8fb3f65d44b798bc06f95a8246bb
|
||||
timeCreated: 1723799785
|
||||
@@ -0,0 +1,36 @@
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Codecs;
|
||||
using DotNetty.Transport.Channels;
|
||||
using System.Collections.Generic;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
|
||||
namespace TestNetty.Service.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Decoder Packet
|
||||
/// </summary>
|
||||
public class TcpDecoderHandler : ByteToMessageDecoder
|
||||
{
|
||||
|
||||
//准备读取的消息长度
|
||||
private int? length;
|
||||
|
||||
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
|
||||
{
|
||||
|
||||
if (length is null && input.ReadableBytes >= 4)
|
||||
{
|
||||
length = input.ReadInt();
|
||||
}
|
||||
|
||||
if (length is not null && input.ReadableBytes >= length)
|
||||
{
|
||||
IByteBuffer result = input.ReadBytes(length.Value);
|
||||
output.Add(NDataUtil.Parse(result.Array));
|
||||
result.Clear();
|
||||
length = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9487ff44b5354bc4843ac7320680c10f
|
||||
timeCreated: 1723773916
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Codecs;
|
||||
using DotNetty.Transport.Channels;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Network.Util;
|
||||
|
||||
namespace TestNetty.Service.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Encoder Packet
|
||||
/// </summary>
|
||||
public class TcpEncoderHandler : MessageToByteEncoder<JNetParam>
|
||||
{
|
||||
protected override void Encode(IChannelHandlerContext context, JNetParam message, IByteBuffer output)
|
||||
{
|
||||
var data = NDataUtil.Encrypt(message);
|
||||
output.WriteInt(data.Length);//4-8
|
||||
output.WriteBytes(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11f81d1e8543432c8226b6c42b605010
|
||||
timeCreated: 1723773916
|
||||
11
JNFrame2/Assets/JNGame/Network/Netty/TCP/TcpPacket.cs
Normal file
11
JNFrame2/Assets/JNGame/Network/Netty/TCP/TcpPacket.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
|
||||
namespace JNGame.Network.Netty.TCP
|
||||
{
|
||||
public class TcpPacket
|
||||
{
|
||||
public int Checkbit;
|
||||
public int Length;
|
||||
public JNetParam Data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5008afe7a554eafb1c684bef86362b0
|
||||
timeCreated: 1723774619
|
||||
154
JNFrame2/Assets/JNGame/Network/Netty/TCP/TcpServerHandler.cs
Normal file
154
JNFrame2/Assets/JNGame/Network/Netty/TCP/TcpServerHandler.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using DotNetty.Transport.Channels;
|
||||
using JNGame.Util.Types;
|
||||
using Plugins.JNGame.Network;
|
||||
using Plugins.JNGame.Network.Action;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace JNGame.Network.Netty.TCP
|
||||
{
|
||||
public class TcpServerHandler : ChannelHandlerAdapter
|
||||
{
|
||||
|
||||
private int _index = 0;
|
||||
public int Next()
|
||||
{
|
||||
return _index++;
|
||||
}
|
||||
|
||||
private JNServerBase root;
|
||||
|
||||
public readonly KeyValue<IChannelHandlerContext, int> ClientInts = new();
|
||||
|
||||
public TcpServerHandler(JNServerBase server)
|
||||
{
|
||||
root = server;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逻辑处理器被添加
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void HandlerAdded(IChannelHandlerContext context)
|
||||
{
|
||||
base.HandlerAdded(context);
|
||||
ClientInts.Add(context,Next());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绑定到线程
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelRegistered(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelRegistered(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 准备就绪
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelActive(IChannelHandlerContext context)
|
||||
{
|
||||
|
||||
base.ChannelActive(context);
|
||||
|
||||
if (!(ClientInts.TryGetValueByKey(context,out var id)))
|
||||
{
|
||||
context.CloseAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[TcpServerHandler] 连接成功: {context.Channel.RemoteAddress}");
|
||||
|
||||
//客户端连接
|
||||
root.Dispatch((int)NActionEnum.ClientConnect,new JNServerParam()
|
||||
{
|
||||
Client = id,
|
||||
Message = Array.Empty<byte>()
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 有数据可读
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="message"></param>
|
||||
public override void ChannelRead(IChannelHandlerContext context, object message)
|
||||
{
|
||||
|
||||
base.ChannelRead(context, message);
|
||||
|
||||
if (message is not JNetParam data) return;
|
||||
|
||||
if (!(ClientInts.TryGetValueByKey(context,out var id)))
|
||||
{
|
||||
context.CloseAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
root.Dispatch(data.HId,new JNServerParam()
|
||||
{
|
||||
Client = id,
|
||||
Message = data.Bytes
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 某次数据读完
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelReadComplete(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelReadComplete(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 被关闭
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelInactive(IChannelHandlerContext context)
|
||||
{
|
||||
|
||||
base.ChannelInactive(context);
|
||||
|
||||
if (!(ClientInts.TryGetValueByKey(context,out var id)))
|
||||
{
|
||||
context.CloseAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[TcpServerHandler] 断开连接: {context.Channel.RemoteAddress}");
|
||||
|
||||
//客户端断开
|
||||
root.Dispatch((int)NActionEnum.ClientDisconnect,new JNServerParam()
|
||||
{
|
||||
Client = id,
|
||||
Message = Array.Empty<byte>()
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消线程(NioEventLoop) 的绑定
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void ChannelUnregistered(IChannelHandlerContext context)
|
||||
{
|
||||
base.ChannelUnregistered(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逻辑处理器被移除
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public override void HandlerRemoved(IChannelHandlerContext context)
|
||||
{
|
||||
base.HandlerRemoved(context);
|
||||
ClientInts.RemoveByKey(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70f2f7800eb14ae189df47eb04e775aa
|
||||
timeCreated: 1723776097
|
||||
@@ -0,0 +1,42 @@
|
||||
using DotNetty.Handlers.Timeout;
|
||||
using DotNetty.Transport.Channels;
|
||||
using DotNetty.Transport.Channels.Sockets;
|
||||
using Plugins.JNGame.Network;
|
||||
using TestNetty.Service.Handlers;
|
||||
|
||||
namespace JNGame.Network.Netty.TCP
|
||||
{
|
||||
public class TcpServerInitializer : ChannelInitializer<ISocketChannel>
|
||||
{
|
||||
|
||||
private JNServerBase root;
|
||||
private TcpServerHandler handler;
|
||||
|
||||
public TcpServerInitializer(JNServerBase server)
|
||||
{
|
||||
root = server;
|
||||
handler = new TcpServerHandler(root);
|
||||
}
|
||||
|
||||
protected override void InitChannel(ISocketChannel channel)
|
||||
{
|
||||
IChannelPipeline pipeline = channel.Pipeline;
|
||||
pipeline.AddLast(new IdleStateHandler(30,30,60 * 5));//心跳
|
||||
pipeline.AddLast(new HeartBeatHandler());
|
||||
pipeline.AddLast("encoder", new TcpEncoderHandler());
|
||||
pipeline.AddLast("decoder", new TcpDecoderHandler());
|
||||
pipeline.AddLast(handler);
|
||||
}
|
||||
|
||||
public IChannelHandlerContext GetClient(int index)
|
||||
{
|
||||
return handler.ClientInts.Value2Key(index);
|
||||
}
|
||||
|
||||
public int[] GetClients()
|
||||
{
|
||||
return handler.ClientInts.Values;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c734c16eb6b4ff98f41bb63524f3209
|
||||
timeCreated: 1723773874
|
||||
8
JNFrame2/Assets/JNGame/Network/Proto.meta
Normal file
8
JNFrame2/Assets/JNGame/Network/Proto.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48ddea52cea7e1145b20a9674aeeca02
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
2812
JNFrame2/Assets/JNGame/Network/Proto/JNSyncMessage.cs
Normal file
2812
JNFrame2/Assets/JNGame/Network/Proto/JNSyncMessage.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
JNFrame2/Assets/JNGame/Network/Proto/JNSyncMessage.cs.meta
Normal file
11
JNFrame2/Assets/JNGame/Network/Proto/JNSyncMessage.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 417922a615a577540b5a5f446a197bdc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
74
JNFrame2/Assets/JNGame/Network/Proto/JNSyncMessage.proto
Normal file
74
JNFrame2/Assets/JNGame/Network/Proto/JNSyncMessage.proto
Normal file
@@ -0,0 +1,74 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "cn.jisol.ngame.proto";
|
||||
|
||||
// ---------------------- 帧同步 --------------------------
|
||||
//帧同步输入
|
||||
message JNFrameInput{
|
||||
int32 nId = 1; //输入的Id
|
||||
optional bytes input = 2; //输入内容
|
||||
int32 clientId = 3; //输入所属的客户端Id
|
||||
}
|
||||
//帧输入列表
|
||||
message JNFrameInputs {
|
||||
repeated JNFrameInput inputs = 1; //输入列表
|
||||
}
|
||||
//帧同步消息
|
||||
message JNFrameInfo {
|
||||
int32 index = 1; //帧数
|
||||
repeated JNFrameInput messages = 2; //消息bytes
|
||||
}
|
||||
//帧同步集合
|
||||
message JNFrameInfos{
|
||||
repeated JNFrameInfo frames = 1; //帧数集
|
||||
}
|
||||
|
||||
//帧同步输入
|
||||
message JNInput {
|
||||
optional string message = 1;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- 状态同步 --------------------------
|
||||
// 状态数据
|
||||
message JNStateData{
|
||||
optional bytes data = 2; //数据
|
||||
}
|
||||
|
||||
// 全量状态
|
||||
message JNStateAllData{
|
||||
int32 NetID = 1; //同步Id
|
||||
map<int64 ,JNStateData> messages = 2; //状态bytes
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
message JNStateItemData{
|
||||
int32 NetID = 1; //同步Id
|
||||
map<int64 ,JNStateData> messages = 2; //状态bytes
|
||||
}
|
||||
|
||||
// --------------------- 状态Tile同步 -----------------------
|
||||
// 状态Tile输入
|
||||
message JNStateTileInputs{
|
||||
int32 tId = 1; //区块Id
|
||||
JNFrameInputs message = 2; //inputs
|
||||
}
|
||||
|
||||
// Tile更新状态
|
||||
message JNStateTileItemData{
|
||||
int32 tId = 1; //区块Id
|
||||
JNStateItemData data = 2;
|
||||
}
|
||||
|
||||
// Tile更新全量状态
|
||||
message JNStateTileAllData{
|
||||
int32 tId = 1; //区块Id
|
||||
JNStateAllData data = 2;
|
||||
}
|
||||
|
||||
//Tile服务器区块信息
|
||||
message JNAddTileServer{
|
||||
int32 tile = 1; //TileId
|
||||
string ip = 2; //IP
|
||||
int32 port = 3; //端口
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5033772dc466fc46a8ac64d8dbc5d00
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
445
JNFrame2/Assets/JNGame/Network/Proto/NActionMessage.cs
Normal file
445
JNFrame2/Assets/JNGame/Network/Proto/NActionMessage.cs
Normal file
@@ -0,0 +1,445 @@
|
||||
// <auto-generated>
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: NActionMessage.proto
|
||||
// </auto-generated>
|
||||
#pragma warning disable 1591, 0612, 3021, 8981
|
||||
#region Designer generated code
|
||||
|
||||
using pb = global::Google.Protobuf;
|
||||
using pbc = global::Google.Protobuf.Collections;
|
||||
using pbr = global::Google.Protobuf.Reflection;
|
||||
using scg = global::System.Collections.Generic;
|
||||
/// <summary>Holder for reflection information generated from NActionMessage.proto</summary>
|
||||
public static partial class NActionMessageReflection {
|
||||
|
||||
#region Descriptor
|
||||
/// <summary>File descriptor for NActionMessage.proto</summary>
|
||||
public static pbr::FileDescriptor Descriptor {
|
||||
get { return descriptor; }
|
||||
}
|
||||
private static pbr::FileDescriptor descriptor;
|
||||
|
||||
static NActionMessageReflection() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"ChROQWN0aW9uTWVzc2FnZS5wcm90byIvCgtOQWN0aW9uRGVtbxIUCgdtZXNz",
|
||||
"YWdlGAEgASgJSACIAQFCCgoIX21lc3NhZ2UiMAoMTkFjdGlvbkRlbW8yEhQK",
|
||||
"B21lc3NhZ2UYASABKAlIAIgBAUIKCghfbWVzc2FnZUIWChRjbi5qaXNvbC5u",
|
||||
"Z2FtZS5wcm90b2IGcHJvdG8z"));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::NActionDemo), global::NActionDemo.Parser, new[]{ "Message" }, new[]{ "Message" }, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::NActionDemo2), global::NActionDemo2.Parser, new[]{ "Message" }, new[]{ "Message" }, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region Messages
|
||||
public sealed partial class NActionDemo : pb::IMessage<NActionDemo>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<NActionDemo> _parser = new pb::MessageParser<NActionDemo>(() => new NActionDemo());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pb::MessageParser<NActionDemo> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::NActionMessageReflection.Descriptor.MessageTypes[0]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public NActionDemo() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public NActionDemo(NActionDemo other) : this() {
|
||||
message_ = other.message_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public NActionDemo Clone() {
|
||||
return new NActionDemo(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "message" field.</summary>
|
||||
public const int MessageFieldNumber = 1;
|
||||
private string message_;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Message {
|
||||
get { return message_ ?? ""; }
|
||||
set {
|
||||
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
/// <summary>Gets whether the "message" field is set</summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool HasMessage {
|
||||
get { return message_ != null; }
|
||||
}
|
||||
/// <summary>Clears the value of the "message" field</summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void ClearMessage() {
|
||||
message_ = null;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as NActionDemo);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool Equals(NActionDemo other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (Message != other.Message) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (HasMessage) hash ^= Message.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
if (HasMessage) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Message);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
if (HasMessage) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Message);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (HasMessage) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(NActionDemo other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.HasMessage) {
|
||||
Message = other.Message;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 10: {
|
||||
Message = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 10: {
|
||||
Message = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class NActionDemo2 : pb::IMessage<NActionDemo2>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<NActionDemo2> _parser = new pb::MessageParser<NActionDemo2>(() => new NActionDemo2());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pb::MessageParser<NActionDemo2> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::NActionMessageReflection.Descriptor.MessageTypes[1]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public NActionDemo2() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public NActionDemo2(NActionDemo2 other) : this() {
|
||||
message_ = other.message_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public NActionDemo2 Clone() {
|
||||
return new NActionDemo2(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "message" field.</summary>
|
||||
public const int MessageFieldNumber = 1;
|
||||
private string message_;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Message {
|
||||
get { return message_ ?? ""; }
|
||||
set {
|
||||
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
/// <summary>Gets whether the "message" field is set</summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool HasMessage {
|
||||
get { return message_ != null; }
|
||||
}
|
||||
/// <summary>Clears the value of the "message" field</summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void ClearMessage() {
|
||||
message_ = null;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as NActionDemo2);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool Equals(NActionDemo2 other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (Message != other.Message) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (HasMessage) hash ^= Message.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
if (HasMessage) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Message);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
if (HasMessage) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Message);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (HasMessage) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(NActionDemo2 other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.HasMessage) {
|
||||
Message = other.Message;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 10: {
|
||||
Message = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 10: {
|
||||
Message = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#endregion Designer generated code
|
||||
11
JNFrame2/Assets/JNGame/Network/Proto/NActionMessage.cs.meta
Normal file
11
JNFrame2/Assets/JNGame/Network/Proto/NActionMessage.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a64c8e0d9371ec4a8dc561dbfe81026
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
12
JNFrame2/Assets/JNGame/Network/Proto/NActionMessage.proto
Normal file
12
JNFrame2/Assets/JNGame/Network/Proto/NActionMessage.proto
Normal file
@@ -0,0 +1,12 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "cn.jisol.ngame.proto";
|
||||
|
||||
message NActionDemo {
|
||||
optional string message = 1;
|
||||
}
|
||||
|
||||
message NActionDemo2 {
|
||||
optional string message = 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e48e0afd082b466081556cb81d66935f
|
||||
timeCreated: 1705996154
|
||||
3
JNFrame2/Assets/JNGame/Network/Util.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Util.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f297d4999ae14dd7a046a1faebd6845a
|
||||
timeCreated: 1706004786
|
||||
45
JNFrame2/Assets/JNGame/Network/Util/NDataUtil.cs
Normal file
45
JNFrame2/Assets/JNGame/Network/Util/NDataUtil.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Google.Protobuf;
|
||||
using Plugins.JNGame.Network.Entity;
|
||||
using Plugins.JNGame.Util;
|
||||
|
||||
namespace Plugins.JNGame.Network.Util
|
||||
{
|
||||
// 网络数据工具类 [请求Id*4,处理Id*4,...参数数据*N]
|
||||
public static class NDataUtil
|
||||
{
|
||||
|
||||
// 解析
|
||||
public static JNetParam Parse(byte[] data)
|
||||
{
|
||||
|
||||
return JNetParam.Build(
|
||||
ToUtil.Byte4ToInt(data.Skip(0).Take(4).ToArray()),
|
||||
ToUtil.Byte4ToInt(data.Skip(4).Take(4).ToArray()))
|
||||
.SetByte(data.Skip(8).Take(data.Length - 8).ToArray());
|
||||
|
||||
}
|
||||
|
||||
// 编码
|
||||
public static byte[] Encrypt(JNetParam param)
|
||||
{
|
||||
|
||||
byte[] id = ToUtil.IntToByte4(param.ID);
|
||||
byte[] hId = ToUtil.IntToByte4(param.HId);
|
||||
byte[] data = Array.Empty<byte>();
|
||||
if(param.Data != null)
|
||||
data = param.Data.ToByteArray();
|
||||
|
||||
byte[] datas = new byte[hId.Length+id.Length+data.Length];
|
||||
Array.Copy(id, 0, datas, 0, id.Length);
|
||||
Array.Copy(hId, 0, datas, id.Length, hId.Length);
|
||||
Array.Copy(data, 0, datas, id.Length + hId.Length, data.Length);
|
||||
return datas;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
3
JNFrame2/Assets/JNGame/Network/Util/NDataUtil.cs.meta
Normal file
3
JNFrame2/Assets/JNGame/Network/Util/NDataUtil.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b05544adb2f44b4af8f86b2bc66a035
|
||||
timeCreated: 1706004790
|
||||
Reference in New Issue
Block a user