C#服务端的微信小游戏——多人在线角色扮演(九)

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

C#服务端的微信小游戏——多人在线角色扮演(九)

微信小程序是个不错的平台,用来做手机小游戏真的很好,简单、通用性好、方便传播。
——茂叔

好了,现在我们开始做客户端了,客户端选择微信小程序,所以我们要下载微信Web开发者工具
所以为什么说腾讯只会抄袭呢,一旦自己搞点东西,连取个名字都不会了,这要是洋人搞的,保不齐取个什么高大上的名字呢……例如TCStadio、TCWARESHOP之类的,一看就觉得高大上。

好吧,中国人就是低调,总之你还没安装的话赶紧安装吧。

申请小程序的过程很简单,自己去微信公众平台去查,我这里就不啰嗦了。

重点就是要记住你的AppIDAppSecret这两个东西。

然后,客户端第一件要做的事情,那就是与服务器建立网络连接,根据腾讯公司给出的文档,wss协议的WebSocket是唯一的选择了。

建立连接

服务端

那么,首先是要在服务器端提供网络连接服务。
因为websocket是基于http协议的,所以,在.Net里面还是使用HttpListener来侦听。
侦听器开始运行了以后,就可以使用HttpListener.GetContext,来接受客户端的连接,这是个同步的方法,会阻断当前的线程,直到有用户连接上来为止。

有客户端连接上来了,就可以HttpListenerContext.Request.IsWebSocketRequest来判断这个http连接是不是一个合法的WebSocket连接了。

然后就HttpListenerContext.AcceptWebSocketAsync,这样就能得到一个与客户端的WebSocket连接了。

为了方便,我们在服务端的GameMonitor项目里定义一个GameConnection类,用来集中处理用户的连接。

在我们的GameServer类里面添加一个HttpListener ClientListener成员,这活本来就该他来干~!
因为侦听会阻断主线程,所以还应该有个侦听的线程ListenThread
还需要一个记录连接的连接池ConnectionPool,这样方便我们管理当前的全部连接。
在构造方法里面对ClientListenerListenThread进行初始化:

private HttpListener ClientListener;
private Thread ListenThread;
public List<GameConnection> ConnectionPool = new List<GameConnection>(1000);
……
public GameServer(MainForm monitor)
        {
            Status = 0;
            Monitor = monitor;
            LOG("GameServer创建成功");
            gGame = new Game(LOG);

            ClientListener = new HttpListener();
            ClientListener.Prefixes.Clear();
            ClientListener.Prefixes.Add("http://localhost:666/");
            ListenThread = new Thread(new ThreadStart(Listen));
        }
……
private void Listen()
        {
            ClientListener.Start();
            while (ClientListener.IsListening)
            {
                try
                {
                    HttpListenerContext context = ClientListener.GetContext();
                    HttpListenerRequest request = context.Request;
                    LOG("收到请求来自:" + request.UserHostAddress + " 的请求");
                    if (request.IsWebSocketRequest)
                    {
                        Task<HttpListenerWebSocketContext> ret = context.AcceptWebSocketAsync(null);
                        ret.Wait();
                        if (ret.Result.WebSocket != null)
                        {
                            if (ConnectionPool.Count < ConnectionPool.Capacity)
                            {
                                GameConnection connection = new GameConnection(request.UserHostAddress, ret.Result.WebSocket, LOG);
                            }
                            else
                            {
                                ret.Result.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "{\"result\":\"fail\",\"msg\":\"连接已满\"}", CancellationToken.None);
                            }
                        }
                    }
                    else
                    {
                        HttpListenerResponse response = context.Response;
                        response.Close();
                    }

                }
                catch (Exception e)
                {
                    LOG(e.Message);
                }
            }
        }

GameConnection类则主要包括连接的基本信息以及接受数据的方法。这里我们让GameConnection连接后发送一个"How are you?"给客户端。然后就开始异步接收客户端发来的信息,收到后LOG出来。

class GameConnection
    {
        public string IP;
        public WebSocket mSocket;
        private Action<string> LOG;

        public GameConnection(string IP,WebSocket mSocket, Action<string> LOGFUN = null)
        {
            this.IP = IP;
            this.mSocket = mSocket;
            LOG = LOGFUN==null? x => { }:LOGFUN;
            LOG("来自 "+IP+" 连接建立成功");
            ArraySegment<byte> segment = new ArraySegment<byte>(Encoding.UTF8.GetBytes("How are you?"));
            mSocket.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
            ReceiveDataAsync();
        }

        private async void ReceiveDataAsync()
        {
            while (mSocket.State == WebSocketState.Open)
            {
                WebSocketReceiveResult result;
                try
                {
                    ArraySegment<byte> receivebuff = new ArraySegment<byte>(new byte[1024]);
                    result = await mSocket.ReceiveAsync(receivebuff, CancellationToken.None);
                    string receiveStr = Encoding.UTF8.GetString(receivebuff.ToArray(), 0, result.Count);
                    LOG("收到来自 " + IP + " 的信息:" + receiveStr);

                }
                catch
                {
                    LOG("连接强行中断");
                    await mSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "{\"result\":\"fail\",\"msg\":\"服务器断开\"}", CancellationToken.None);
                }
            }
            LOG("连接已断开");
        }
    }

GameServer类的启动和停止方法管理侦听线程:

public void StartUp()
        {
            if (Status == 0)
            {
                gGame.Run();
                Status = 1;
                ListenThread.Start();
                LOG("GameServer启动成功");
            }
            else
            {
                LOG("GameServer当前处于启动状态,请勿重复启动");
            }
        }
        public void ShutDown()
        {
            if (Status == 1)
            {
                ClientListener.Stop();
                gGame.Stop();
                Status = 0;                
                LOG("GameServer停机成功");
            }
            else
            {
                LOG("GameServer当前处于停机状态,无需再次停机");
            }
        }

好了,万事俱备,就等客户端连接上来了。

客户端

启动微信web开发者工具,新建一个已经注册的小游戏,填入AppID,路径,名字,然后开发者工具会自动为你搭建一个“打飞机”游戏的模板……玩一下,看看你能得多少分。然后把所有文件都删除,遇到无法删除的文件夹就退出重启再删除。最后只剩下三个文件:
在这里插入图片描述
然后打开game.js文件,删除所有内容。
这个文件是微信小游戏默认启动的脚本,所以,我们可以用它来调试一下我们的网络连接。
在game.js文件里输入代码:

wx.connectSocket({
  url: 'ws://localhost:666/',
  method: "GET",
  success(res){
    console.log("Socket successed:")
    console.log(res)
    wx.onSocketOpen(
      (res) => {
        console.log("Socket opened:")
        console.log(res)
      }
    )
    wx.onSocketClose(
      (res) => {
        console.log("Socket closed:")
        console.log(res)
      }
    )
    wx.onSocketError((res) => {
      console.log("Socket error:")
      console.log(res)
    })
    wx.onSocketMessage((res)=>{
      console.log("got message:")
      console.log(res)
      wx.sendSocketMessage(
        {
          data:"Fine!Thank you,and you?",
          success:(res)=>{
            console.log("send msg:")
            console.log(res)
          }
        }
      );
    })
  },
  fail(res){
    console.log("Socket failed:")
    console.log(res)
  }
})

注意,一定要勾选这个:
在这里插入图片描述
然后,我们先运行服务器端,启动GameServer
再到微信web开发工具里面,按Ctrl+B,开发工具会自动在模拟器上编译和运行这个脚本。

运行结果如下:
客户端:
在这里插入图片描述
服务器端:
在这里插入图片描述
天啦~他们沟通得很顺畅啊!

基本的沟通管道已经调通了,下一步,我们将要实现真正有意义的指令传递和数据下发了。

上一篇:C#服务端的微信小游戏——多人在线角色扮演(八)
下一篇:C#服务端的微信小游戏——多人在线角色扮演(十)

请用微信扫描查看游戏效果演示

演示入口

猜你喜欢

转载自blog.csdn.net/foomow/article/details/91653105