Socket服务器通讯架构
学习自www.u3dol.com,悠游的免费课程
每日学习,每日记录
类图
以每一个角色为起点 一个角色就对应了一个客户端,每个客户端发送的数据有背包数据,任务数据…等等。客户端和服务器之间的通讯也就是传递数据,那么服务器怎么知道客户端传递来的是什么数据,这时候就要客户端与服务器规定一个协议,双方都按照这个协议来传递并且解析。
规定通讯协议
通讯协议客户端与服务器都要有并且是一样的 用来传递与解析数据
协议实体
传递数据包也就是传递的是字节数组,Json字符串也可以转成字节数组传递,并且容易解析。但是Json转换成的字节数组与内存流的形式相比体积大概翻了一倍,在用户体验就是流量翻倍,所以用内存流的形式来进行传递。如果以流的形式传递,那么不同模块的数据需要进行区分。可以根据一个编号进行区分例如背包的数据编号就是1001。
协议常量类
协议编号接口
观察者模式
观察者模式可以很好的将不同的消息分配给不同的模块。
客户端向服务器发送数据,服务器将数据交给观察者分发,观察者根据数据中的协议编号分发给具体模块
建立服务器与客户端连接
服务器端
服务器端Socket,用来与各个客户端进行连接。
建立一个控制台程序用来做主入口进行Socket的初始化
这里用Tcp协议,开启一个线程单独来进行客户端的连接
每连接一个客户端就代表有一个角色 所以创建一个角色并为角色中的ClientSocket进行赋值
服务器需要管理所有客户端也就是所有角色所以应该有一个角色管理类来存储所有的角色,客户端连接到服务器时就想管理器中集合添加,断开连接时在集合中移除方便服务器管理
服务器端的 ClientSocket
具体的每一个客户端,用来传递与接收数据
客户端
客户端连接服务器Socket 指定IP和端口就可以连接 开启连接时开始接收消息
客户端发送数据
发送数据与接收数据客户端与服务器端基本一样,来记录客户端发送数据,服务器端来接收数据
发送数据的流程为:
封装数据包 —> 将封装好的数据包加入传递队列—> 调用检查发送数据队列的委托—> 委托中检查消息队列中如果有数据则将数据发送给服务器
封包
因为读取的时候需知道读取的数据字节长度,则先写入长度,再写入内容解析时根据长度来解析内容
服务器接收消息
服务器接收消息流程:
解析数据包为当前传递过来的协议编号及内容—> 用观察者模式将解析得到的数据分发给各个模块
接收消息用这个方法,在回调中执行解析的逻辑,详细代码在最后
XXXDBMoudel
开始时在观察者注册监听当前模块所对应的数据,当有数据传递过来则调用委托来进行解析并且处理逻辑
接收消息则需要用到观察者模式,根据不同的协议ID将数据派发给不同的模块
ClientSocket代码
using Assets.Scripts.Common.Net.Proto;
using GameSeverApp.Common;
using ns;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace GameSeverApp
{
/// <summary>
/// 客户端连接对象
/// 负责和客户端进行通讯
/// </summary>
public class ClientSocket
{
/// <summary>
/// 客户端Socket
/// </summary>
private Socket m_Socket;
/// <summary>
/// 接收数据的线程
/// </summary>
private Thread m_ReceiveThread;
/// <summary>
/// 接受数据的字节缓冲区
/// </summary>
private byte[] m_ReceiveBuffer = new byte[10240];
/// <summary>
/// 当前客户端所对应的角色对象
/// </summary>
private Role m_Role;
/// <summary>
/// 接受数据的内存流
/// </summary>
private MyMemoryStream m_MemoryStream = new MyMemoryStream();
#region 发送消息所需变量