C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信

2019-12-30 12:23:35于海丽

二、Unity中使用Socket实现时时通信

通信应该实现的功能:

  • 服务器可以时时监听多个客户端
  • 服务器可以时时监听某一个客户端消息
  • 服务器可以时时给某一个客户端发消息
  • 首先我们需要定义一个客户端对象
    
    using System;
    using System.Net.Sockets;
    
    // 表示一个客户端
    public class NetUserToken {
     //连接客户端的Socket
     public Socket socket;
     //用于存放接收数据
     public byte[] buffer;
    
     public NetUserToken()
     {
      buffer = new byte[1024];
     }
    
     // 接受消息
     // < param name="data">Data.< /param>
     public void Receive(byte[] data)
     {
      UnityEngine.Debug.Log("接收到消息!");
     }
    
     // 发送消息
     //< param name="data">Data.< /param>
     public void Send(byte[] data)
     {  
    
     }
    }
    
    using System;
    using System.Net.Sockets;
     
    // 表示一个客户端
    public class NetUserToken {
     //连接客户端的Socket
     public Socket socket;
     //用于存放接收数据
     public byte[] buffer;
     
     public NetUserToken()
     {
      buffer = new byte[1024];
     }
     
     // 接受消息
     // < param name="data">Data.< /param>
     public void Receive(byte[] data)
     {
      UnityEngine.Debug.Log("接收到消息!");
     }
     
     // 发送消息
     //< param name="data">Data.< /param>
     public void Send(byte[] data)
     {  
     
     }
    }
    
    

     

    然后实现我们的服务器代码

    
    using System.Collections;
    using System.Collections.Generic;
    using System.Net;
    using System;
    using System.Net.Sockets;
    
    public class NetServer{
     //单例脚本
     public static readonly NetServer Instance = new NetServer();
     //定义tcp服务器
     private Socket server;
     private int maxClient = 10;
     //定义端口
     private int port = 35353;
     //用户池
     private Stack<NetUserToken> pools;
     private NetServer()
     {
      //初始化socket
      server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      server.Bind(new IPEndPoint(IPAddress.Any, port));
    
     }
    
     //开启服务器
     public void Start()
     {
      server.Listen(maxClient);
      UnityEngine.Debug.Log("Server OK!");
      //实例化客户端的用户池
      pools = new Stack<NetUserToken>(maxClient);
      for(int i = 0; i < maxClient; i++)
      {
       NetUserToken usertoken = new NetUserToken();
       pools.Push(usertoken);
      }
      //可以异步接受客户端, BeginAccept函数的第一个参数是回调函数,当有客户端连接的时候自动调用
      server.BeginAccept (AsyncAccept, null);
     }
    
     //回调函数, 有客户端连接的时候会自动调用此方法
     private void AsyncAccept(IAsyncResult result)
     {
      try {
       //结束监听,同时获取到客户端
       Socket client = server.EndAccept(result);
       UnityEngine.Debug.Log("有客户端连接");
       //来了一个客户端
       NetUserToken userToken = pools.Pop();
       userToken.socket = client;
       //客户端连接之后,可以接受客户端消息
       BeginReceive(userToken);
    
       //尾递归,再次监听是否还有其他客户端连入
       server.BeginAccept(AsyncAccept, null);
      } catch (Exception ex) {
       UnityEngine.Debug.Log(ex.ToString());
      }
     }
    
     //异步监听消息
     private void BeginReceive(NetUserToken userToken)
     {
      try {
       //异步方法
       userToken.socket.BeginReceive(userToken.buffer, 0, userToken.buffer.Length, SocketFlags.None,
               EndReceive, userToken);
      } catch (Exception ex) {
       UnityEngine.Debug.Log(ex.ToString());
      }
     }
    
     //监听到消息之后调用的函数
     private void EndReceive(IAsyncResult result)
     {
      try {
       //取出客户端
       NetUserToken userToken = result.AsyncState as NetUserToken;
       //获取消息的长度
       int len = userToken.socket.EndReceive(result);
       if(len > 0)
       { 
        byte[] data = new byte[len];
        Buffer.BlockCopy(userToken.buffer, 0, data, 0, len);
        //用户接受消息
        userToken.Receive(data);
        //尾递归,再次监听客户端消息
        BeginReceive(userToken);
       }
    
      } catch (Exception ex) {
       UnityEngine.Debug.Log(ex.ToString());
      }
     }
    }
    
    using System.Collections;
    using System.Collections.Generic;
    using System.Net;
    using System;
    using System.Net.Sockets;
     
    public class NetServer{
     //单例脚本
     public static readonly NetServer Instance = new NetServer();
     //定义tcp服务器
     private Socket server;
     private int maxClient = 10;
     //定义端口
     private int port = 35353;
     //用户池
     private Stack<NetUserToken> pools;
     private NetServer()
     {
      //初始化socket
      server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      server.Bind(new IPEndPoint(IPAddress.Any, port));
     
     }
     
     //开启服务器
     public void Start()
     {
      server.Listen(maxClient);
      UnityEngine.Debug.Log("Server OK!");
      //实例化客户端的用户池
      pools = new Stack<NetUserToken>(maxClient);
      for(int i = 0; i < maxClient; i++)
      {
       NetUserToken usertoken = new NetUserToken();
       pools.Push(usertoken);
      }
      //可以异步接受客户端, BeginAccept函数的第一个参数是回调函数,当有客户端连接的时候自动调用
      server.BeginAccept (AsyncAccept, null);
     }
     
     //回调函数, 有客户端连接的时候会自动调用此方法
     private void AsyncAccept(IAsyncResult result)
     {
      try {
       //结束监听,同时获取到客户端
       Socket client = server.EndAccept(result);
       UnityEngine.Debug.Log("有客户端连接");
       //来了一个客户端
       NetUserToken userToken = pools.Pop();
       userToken.socket = client;
       //客户端连接之后,可以接受客户端消息
       BeginReceive(userToken);
     
       //尾递归,再次监听是否还有其他客户端连入
       server.BeginAccept(AsyncAccept, null);
      } catch (Exception ex) {
       UnityEngine.Debug.Log(ex.ToString());
      }
     }
     
     //异步监听消息
     private void BeginReceive(NetUserToken userToken)
     {
      try {
       //异步方法
       userToken.socket.BeginReceive(userToken.buffer, 0, userToken.buffer.Length, SocketFlags.None,
               EndReceive, userToken);
      } catch (Exception ex) {
       UnityEngine.Debug.Log(ex.ToString());
      }
     }
     
     //监听到消息之后调用的函数
     private void EndReceive(IAsyncResult result)
     {
      try {
       //取出客户端
       NetUserToken userToken = result.AsyncState as NetUserToken;
       //获取消息的长度
       int len = userToken.socket.EndReceive(result);
       if(len > 0)
       { 
        byte[] data = new byte[len];
        Buffer.BlockCopy(userToken.buffer, 0, data, 0, len);
        //用户接受消息
        userToken.Receive(data);
        //尾递归,再次监听客户端消息
        BeginReceive(userToken);
       }
     
      } catch (Exception ex) {
       UnityEngine.Debug.Log(ex.ToString());
      }
     }
    }