微信小程序是个不错的平台,用来做手机小游戏真的很好,简单、通用性好、方便传播。
——茂叔
好了,现在我们开始做客户端了,客户端选择微信小程序,所以我们要下载微信Web开发者工具
。
所以为什么说腾讯只会抄袭呢,一旦自己搞点东西,连取个名字都不会了,这要是洋人搞的,保不齐取个什么高大上的名字呢……例如TCStadio、TCWARESHOP之类的,一看就觉得高大上。
好吧,中国人就是低调,总之你还没安装的话赶紧安装吧。
申请小程序的过程很简单,自己去微信公众平台去查,我这里就不啰嗦了。
重点就是要记住你的AppID
,AppSecret
这两个东西。
然后,客户端第一件要做的事情,那就是与服务器建立网络连接,根据腾讯公司给出的文档,wss
协议的WebSocket
是唯一的选择了。
建立连接
服务端
那么,首先是要在服务器端提供网络连接服务。
因为websocket
是基于http
协议的,所以,在.Net
里面还是使用HttpListener
来侦听。
侦听器开始运行了以后,就可以使用HttpListener.GetContext
,来接受客户端的连接,这是个同步的方法,会阻断当前的线程,直到有用户连接上来为止。
有客户端连接上来了,就可以HttpListenerContext.Request.IsWebSocketRequest
来判断这个http
连接是不是一个合法的WebSocket
连接了。
然后就HttpListenerContext.AcceptWebSocketAsync
,这样就能得到一个与客户端的WebSocket
连接了。
为了方便,我们在服务端的GameMonitor
项目里定义一个GameConnection
类,用来集中处理用户的连接。
在我们的GameServer
类里面添加一个HttpListener ClientListener
成员,这活本来就该他来干~!
因为侦听会阻断主线程,所以还应该有个侦听的线程ListenThread
。
还需要一个记录连接的连接池ConnectionPool
,这样方便我们管理当前的全部连接。
在构造方法里面对ClientListener
和ListenThread
进行初始化:
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#服务端的微信小游戏——多人在线角色扮演(十)
请用微信扫描查看游戏效果演示