手机版
网站地图
美文美图
最新动态
你好,欢迎访问
好美文阅读网
个性皮肤
搜索
网站首页
美文
文章
散文
日记
诗歌
小说
故事
句子
作文
签名
祝福语
情书
范文
读后感
文学百科
美文摘抄
节日文章
名家散文
网名大全
座右铭
口号大全
面试技巧
说说大全
阅读答案
诗词默写
流言蜚语
节日祝福
好句子
经典台词
谚语大全
亲情故事
友情故事
表白情书
工作报告
活动总结
心得体会
专题汇总
美文网首页
Unity3D游戏开发
网络框架
网络框架
作者:
我家菇凉
| 来源:发表于
2019-11-28 19:56 被阅读0次
客户端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mManagerSocket :Singleton<mManagerSocket>
{
// 消息队列中的元素类型
class MsgItem
{
//消息类型
public int msgid;
public byte[] msg;
}
// 代参数的委托类
public delegate void OnMessage_CenterFunce( byte[] msg);
// 每一个客户端给服务器的消息ID对应一个委托类,放入字典管理起来
public Dictionary<int, OnMessage_CenterFunce> dic = new Dictionary<int, OnMessage_CenterFunce>();
// 消息队列,用于存储从服务器接受来的包,便于主线程获取处理
private Queue<MsgItem> all_Msgitem = new Queue<MsgItem>();
// 注册消息处理回调
public void OnResour_Funces(int msgid, OnMessage_CenterFunce resFunces)
{
//定义一个准备接受从那个字典类去除来的属性
OnMessage_CenterFunce funce = null;
//判断根据消息类型拿出对应的委托类
if (dic.TryGetValue(msgid, out funce))
{
//注册消息回调函数
funce += resFunces;
}
else
{
//如果没有加入到字典管理起来
dic.Add(msgid, resFunces);
}
}
/// <summary>
/// 对队里中的数据进行发布
/// </summary>
/// <param name="msgid"></param>
/// <param name="clientid"></param>
/// <param name="msg"></param>
public void OnMessagehandling(int msgid,byte[] msg)
{
//根据从队列去处的消息类型拿到集合内对应的事件类
OnMessage_CenterFunce funce = null;
//判断根据消息类型拿出对应的委托类
if (dic.TryGetValue(msgid, out funce))
{
//事件发布
funce(msg);
}
}
// 把收到的消息压入队列
public void All_Enqueue(int msgid, byte[] msg)
{
//建立一个元素对象
MsgItem item = new MsgItem();
//同上(消息类型)
item.msgid = msgid;
//把传入进来的具体消息复制到队列类中
item.msg = msg;
//防止多个客户端连接进来
lock (all_Msgitem)
{
//把消息压入队列
all_Msgitem.Enqueue(item);
}
}
// 处理该客户端消息队列中的消息
public void Dele_Dequeue()
{
//一次性处理完所有的积累消息
while (true)
{
//如果消息处里完毕了,退出
if (all_Msgitem.Count <= 0)
{
return;
}
//处理消息出队
MsgItem item = all_Msgitem.Dequeue();
//调用--- 事件发布
OnMessagehandling(item.msgid,item.msg);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System;
using System.IO;
public class NetClicent : Singleton<NetClicent>
{
// 异步通讯所用的附带数据类型
class AscyData
{
// 消息ID
public int mesid;
// 当前写入位置
public int pos;
// 缓冲区
public byte[] buff;
}
// 消息ID长度
public const int MSG_ID_SIZE = sizeof(int);
// 包头长度
public const int HONE_SIZE = sizeof(ushort);
public Socket mServerSocket;
public void StartServer(string mIP, int mPort)
{
mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint IPE = new IPEndPoint(IPAddress.Parse(mIP), mPort);
try
{
mServerSocket.Connect(IPE);
}
catch (System.Exception)
{
Debug.Log("连接失败");
throw;
}
Debug.Log("连接服务端成功。。。");
Start_Subpackage();
}
//异步读取包处
private void Start_Subpackage()
{
//异步读取所有用到的属性,读取从包头加消息类型开始
AscyData data = new AscyData()
{
buff = new byte[HONE_SIZE + MSG_ID_SIZE],
};
mServerSocket.BeginReceive(data.buff, 0, data.buff.Length, SocketFlags.None, BeginHone, data);
}
private void BeginHone(IAsyncResult ar)
{
//拿到发送过来的长度
int len = mServerSocket.EndReceive(ar);
//从系统中取出之前传入的参数
AscyData data = ar.AsyncState as AscyData;
//判断包的长度和MSGID是否都接受成功
if (len + data.pos == data.buff.Length)
{
//从接受完的字节数组中取出总长度 0代表从0开始全部转换完毕
ushort paselen = BitConverter.ToUInt16(data.buff, 0);
//从接受完的字节数组中取出消息的ID类型 2代表从0开始只转换两个字节
int mesid = BitConverter.ToInt32(data.buff, HONE_SIZE);
//开启一个异步读取包体的对象存储的位置
AscyData da = new AscyData()
{
buff = new byte[paselen - MSG_ID_SIZE],
mesid = mesid,
};
mServerSocket.BeginReceive(da.buff, 0, da.buff.Length, SocketFlags.None, BeginBody, da);
}
else
{
//没有读取完则继续读取包头的剩余部分
data.pos += len;
//异步开始读取包体
mServerSocket.BeginReceive(data.buff, data.pos, data.buff.Length - data.pos, SocketFlags.None, BeginHone, data);
}
}
private void BeginBody(IAsyncResult ar)
{
//同上 --他们所拿到的数据和长度都是真实的数据
int len = mServerSocket.EndReceive(ar);
//获取之前开启存储数据的类的对象
AscyData data = ar.AsyncState as AscyData;
//判断是否读取完毕,读取完毕就放入队列
if (len + data.pos == data.buff.Length)
{
mManagerSocket.Instance .All_Enqueue(data.mesid,data.buff);
//开启读取下一个包
Start_Subpackage();//再次进行回调
}
else
{
//把么有读取完的数据增加到有效数据的末尾
data.pos += len;
mServerSocket.BeginReceive(data.buff, data.pos, data.buff.Length - data.pos, SocketFlags.None, BeginHone, data);
}
}
//服务返回给客户端发送消息
public void Send(int msgid, byte[] msg)
{
//这个要倒IO包 他相当于一个记忆 短暂记忆的一个流 全部拿到发出去
using (MemoryStream mm = new MemoryStream())
{
//拿到你要发送的总长度
ushort length = (ushort)(msg.Length + MSG_ID_SIZE);
//通过IO流的方式连接到MemoryStream
BinaryWriter bw = new BinaryWriter(mm);
//包头放置数据长度,2个字节
bw.Write(length);
//消息类型
bw.Write(msgid);
//具体数据
bw.Write(msg);
//两种写法 这种是全部发送 也没问题
// mServerSocket.Send(mm.GetBuffer());
//返回给客户端消息处,参数一全部的数据包,参数二发送的长度(要加上包头的长度)
mServerSocket.Send(mm.GetBuffer(), length + HONE_SIZE, SocketFlags.None);
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Google.Protobuf;
using MyUser;
//意思是 S——服务端 2——TO C --客户端
public enum S2C
{
TankLoginResult = 0,
Generate_playerlist = 1,
Anaphase_Player = 2,
WantMove = 3,
}
/// <summary>
/// 所有客户端给服务器的消息id类型
/// </summary>
//客户端发送给服务端
public enum C2S
{
TankLoginResult = 0,
Generate_playerlist = 1,
Anaphase_Player = 2,
WantMove = 3,
}
相关文章
网友评论
Unity3D游戏开发
本文标题:
网络框架
本文链接:
https://www.haomeiwen.com/subject/qykiwctx.html
延伸阅读
那年盛夏诗歌
环境监察队工作总结范文
优秀教师学习心得范文
华胥引的读后感300字
《Its red》教学反思范文
农资购销的合同范本
竞选中队委优秀演讲稿
辞金蹈海的成语解释
《世纪宝鼎》公开课教案设计
因为爱你,所以牵挂
今生今世红尘醉——美到
一个90后的内心独白
致已逝去的高中年华
深度阅读
您也可以注册成为美文阅读网的作者,发表您的原创作品、分享您的心情!
情人节
母亲节
重阳节
清明节
端午节
植树节
元宵节
妇女节
愚人节
圣诞节
父亲节
教师节
儿童节
劳动节
青年节
建军节
万圣节
平安夜
光棍节
中秋节
国庆节
感恩节
腊八节
更多话题
栏目导航
Unity3D游戏开发
摄影
故事
互联网
读书
旅行
热点阅读
感恩遇见
adb logcat
孩子,知不知道你在干什么
距离我的生日还有21天
太阳从东方升起
好故事是修改出来的。
友谊的小船
一丝浅笑让我心发烫
2019-11-28
南怀瑾
Unity3D游戏开发
有限状态机概念
状态机用法
游戏后期优化
网络框架
Unity 3D 游戏优化
代码优化
unity-遮挡剔除OcclusionCulling
行为树(Behavior Tree)
行为树(behavior tree)
DoTween
网友评论