极简网络框架
//客户端
==========首先来个单例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T> where T:class,new()
{
private static T _instance;
private static readonly Object _lock = new Object();
public static T Instance
{
get
{
if(_instance == null)
{
lock(_lock)
{
if (_instance == null)
{
_instance = new T();
}
}
}
return _instance;
}
}
}
//==================消息中心
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MessageCenter : Singleton<MessageCenter>
{
Dictionary<int, Action<object>> dic = new Dictionary<int, Action<object>>();
public void AddListen(int id,Action<object> action)
{
if(dic.ContainsKey(id))
{
dic[id] += action;
}
else
{
dic.Add(id, action);
}
}
public void RemoveListen(int id,Action<object> action)
{
if(dic.ContainsKey(id))
{
dic[id] -= action;
if(dic[id] == null)
{
dic.Remove(id);
}
}
}
public void BroadCast(int id , params object[] objs)
{
if(dic.ContainsKey(id))
{
dic[id](objs);
}
}
}
//=============unity 中的启动项
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Client_NetManager.Instance.Init();
}
// Update is called once per frame
void Update()
{
Client_NetManager.Instance.UpData();
}
private void OnApplicationQuit()
{
Client_NetManager.Instance.Close();
}
}
//============客户端框架
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.Linq;
using UnityEngine;
using System;
public class Client_NetManager : Singleton<Client_NetManager>
{
private Socket socket;
public Queue<byte[]> que = new Queue<byte[]>();
public byte[] data = new byte[1024];
public byte[] stream = new byte[0];
public void Init()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect("127.0.0.1", 12345, OnConnect, null);
}
private void OnConnect(IAsyncResult ar)
{
socket.EndConnect(ar);
socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
IPEndPoint ip = socket.LocalEndPoint as IPEndPoint;
MID.MyIp = ip.Address + ":" + ip.Port;
}
private void OnReceive(IAsyncResult ar)
{
try
{
int len = socket.EndReceive(ar);
if (len > 0)//有数据
{
byte[] data0 = new byte[len];
Buffer.BlockCopy(data, 0, data0, 0, len);
stream = stream.Concat(data0).ToArray();
while (stream.Length >= 2)
{
ushort oneLen = BitConverter.ToUInt16(stream, 0);
int allLen = oneLen + 2;
if (stream.Length >= allLen)
{
byte[] oneData = new byte[oneLen];
Buffer.BlockCopy(stream, 2, oneData, 0, oneLen);
que.Enqueue(oneData);
int syLen = stream.Length - allLen;
if (syLen > 0)
{
byte[] syData = new byte[syLen];
Buffer.BlockCopy(stream, allLen, syData, 0, syLen);
stream = syData;
}
else
{
stream = new byte[0];
break;
}
}
else
{
break;
}
}
socket.BeginReceive(data, 0, data.Length, SocketFlags.None, OnReceive, null);
}
}
catch (Exception e)
{
Debug.Log(e);
}
}
public void UpData()
{
while (que.Count>0)
{
byte[] oneData = que.Dequeue();
int id = BitConverter.ToInt32(oneData, 0);
byte[] body = new byte[oneData.Length - 4];
Buffer.BlockCopy(oneData, 4, body, 0, body.Length);
MessageCenter.Instance.BroadCast(id, body);
}
}
public void Send(int id, byte[] body)
{
byte[] head = BitConverter.GetBytes(id);
byte[] len = BitConverter.GetBytes((ushort)(head.Length + body.Length));
byte[] data = new byte[0];
data = data.Concat(len).ToArray();
data = data.Concat(head).ToArray();
data = data.Concat(body).ToArray();
socket.BeginSend(data, 0, data.Length, SocketFlags.None, OnSend, null);
}
private void OnSend(IAsyncResult ar)
{
int len = socket.EndSend(ar);
Console.WriteLine("发送长度====》" + len);
}
public void Close()
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
//=========一个消息号的类 静态或者是常量类,为了不让发送消息乱(下面是个例子)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MID : MonoBehaviour
{
public static string MyIp = null;
//登录
public const int S_C_LOGIN = 1001;
public const int C_S_LOGIN = 1002;
//玩家上线
public const int S_C_MYONLINE = 1003;
public const int S_C_OTHERONLINE = 1004;
//初始创建物品
public const int S_C_CREATGOODS = 1005;
//删除物品 ,生成物品
public const int S_C_SYNGOOD = 1006;
public const int C_S_SYNGOOD = 1007;
//移动
public const int S_C_MOVE = 1008;
public const int C_S_MOVE = 1009;
//离线
public const int OUTLINE = 1010;
//创建篝火
public const int C_S_CREATGH = 1011;
public const int S_C_CREATGH = 1012;
//进食
public const int S_C_EATMEET = 1013;
public const int C_S_EATMEET = 1014;
//掉血
public const int S_C_DIAOXUE = 1005;
public const int C_S_DIAOXUE = 1006;
}
//==============================服务器内容
//同样的消息中心 / 单例 / 消息号类 来一套
//服务器的启动项
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Six_MonthExam_Sever
{
public class Program
{
static void Main(string[] args)
{
Sever_NetManager.Instance.Init();
Console.ReadKey();
}
}
}
// ===========服务器的框架
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Six_MonthExam_Sever
{
public class Sever_NetManager:Singleton<Sever_NetManager>
{
private Socket socket;
public List<Client> clients = new List<Client>();
public void Init()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, 12345));
socket.Listen(5);
Console.WriteLine("服务器启动");
socket.BeginAccept(OnAccept, null);
}
private void OnAccept(IAsyncResult ar)
{
Client client = new Client();
client.socket = socket.EndAccept(ar);
IPEndPoint ip = client.socket.RemoteEndPoint as IPEndPoint;
client.ip = ip.Address + ":" + ip.Port;
clients.Add(client);
Console.WriteLine("客户端"+client.ip+"已连接");
client.socket.BeginReceive(client.data, 0, client.data.Length, SocketFlags.None, OnReceive, client);
socket.BeginAccept(OnAccept, null);
}
private void OnReceive(IAsyncResult ar)
{
try
{
Client client = ar.AsyncState as Client;
int len = client.socket.EndReceive(ar);
if(len>0)
{
byte[] data0 = new byte[len];
Buffer.BlockCopy(client.data, 0, data0, 0, len);
client.stream = client.stream.Concat(data0).ToArray();
while (client.stream.Length>=2)
{
ushort oneLen = BitConverter.ToUInt16(client.stream, 0);
int allLen = oneLen + 2;
if(client.stream.Length>=allLen)
{
byte[] oneData = new byte[oneLen];
Buffer.BlockCopy(client.stream, 2, oneData, 0, oneData.Length);
int id = BitConverter.ToInt32(oneData, 0);
byte[] body = new byte[oneData.Length - 4];
Buffer.BlockCopy(oneData, 4, body, 0, oneData.Length - 4);
MessageManager.Instance.BroadCast(id, body, client);
int syLen = client.stream.Length - allLen;
if(syLen>0)
{
byte[] syData = new byte[syLen];
Buffer.BlockCopy(client.stream, allLen, syData, 0, syLen);
client.stream = syData;
}
else
{
client.stream = new byte[0];
break;
}
}
else
{
break;
}
}
client.socket.BeginReceive(client.data, 0, client.data.Length, SocketFlags.None, OnReceive, client);
}
else
{
client.socket.Shutdown(SocketShutdown.Both);
Console.WriteLine(client.ip+"离线");
clients.Remove(client);
client.socket.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public void Send(int id,byte[] body,Client client)
{
byte[] head = BitConverter.GetBytes(id);
byte[] len = BitConverter.GetBytes((ushort)(head.Length + body.Length));
byte[] data = new byte[0];
data = data.Concat(len).ToArray();
data = data.Concat(head).ToArray();
data = data.Concat(body).ToArray();
client.socket.BeginSend(data, 0, data.Length, SocketFlags.None, OnSend, client);
}
private void OnSend(IAsyncResult ar)
{
Client client = ar.AsyncState as Client;
int len = client.socket.EndReceive(ar);
Console.WriteLine("发送长度:"+len);
}
public void SendAll(int id,byte[] body)
{
foreach (var item in clients)
{
Send(id, body, item);
}
}
}
}
//================谷歌旗下的Protobuf(示例)
package xxx;
syntax = "proto3";
message helloworld
{
string zzz= 123;
string yyy= 0;
}
//================Protobuf解和填
//发送
C_S_Login c = new C_S_Login();
c.MyName = user.text;
//发送消息给客户端
Client_NetManager.Ins.Send(MID.C_S_LOGIN,c.ToByteArray());
//接收
object[] arr = obj as object[];
byte[] body = arr[0] as byte[];
S_C_Login s = S_C_Login.Parser.ParseFrom(body);
//记得引用命名空间
using zzz;//pb包名
using Google.Protobuf;//谷歌
本文来自博客园,作者:{old_Host},转载请注明原文链接:https://www.cnblogs.com/zanzz/p/17262617.html

浙公网安备 33010602011771号