上一章:壹:十行代码带你打穿客户端和服务端的通信
上一章我们学习了服务端与客户端之间的相互通信,现在我们来做一个极简的聊天系统。如果你身陷荒野也许可以考虑用它来做一个建议文字对话机。
这次我们先从客户端开始搭建起
通过教程我们将会建立一个上面这样极简的界面。
思路:
我们的思路是这样的,我们做两个客户端一个输入用户名client1,另外一个输入用户名client2,我们的目标是client1通过服务端可以和client2相互交换消息。
步骤:
先做一个注册按钮,然后我们在输入框里面输入我们的名字,点击注册后注册按钮把自己的名字发给服务器,以便服务器日后知道谁是client1谁是client2然后就可以把对应的消息发送给对应的客户端了
当然在注册之后,这个注册按钮也就没有用了,我们就可以销毁它。然后页面上只留下一个发送按钮,再次输入文字,点击发送就可以发送信息了。
开始:
首先我们通过cocos新建一个项目,并且在资源管理器创建如下文件(如果你不会创建可以看看上一个教程)
(1)一个叫Client的场景
(2)一个也叫Client的脚本
然后我们从“内置控件”栏拖入如下几个控件
(1)文本标签:
用途:用来显示服务端发送过来的信息
(2)文本输入框
用途:用来输入要发送的消息
(3)按钮
用途:用来触发发送消息的事件
当然在给服务端发送消息之前为了让服务端知道我们是谁,所以我们要先给自己起一个名字来告诉服务端,以便服务端知道有了我们的消息后怎么传给我们。
所以我们现在发送按钮正上方再创建一个一模一样大小的按钮。并且把它的文字改为“注册”覆盖在发送按钮上。
下面是如何修改按钮的名字:展开按钮,选中子节点中的Label节点,然后在属性栏如图处修改。以上所有控件的名字修改都可以参考这个步骤。
由于Cocos默认相同的按钮重叠只能触发最上面按钮的点击事件,我们这个教程为了简单先用这种最简单的处理方式来阐明道理,将来会和大家好好的聊一下制作规范。
现在我们来编辑Client脚本
我们首先点击选中Canvas,然后拖拽Client脚本进入Canvas的属性栏
然后点击Client脚本打开
首先我们来监听一下输入框的文本变化
我们首先在start()函数最上面声明一个message的变量用来保存文本框的文本变化。
this.message = '';
然后我们回到界面选中输入框,在它右侧属性中有一个属性用来监听文本变化Text Changed,我们把它后面的值赋予 1
接下来我们在脚本中准备一个接入输入框值变化的函数(cocos 默认这么写函数赋予给输入框就可以接受文本变化的输入事件)
onTextChanged: function(text, editbox, customEventData) {
console.log("文本变化",text);
},
注意这个函数写在start()函数后面,中间用逗号隔开
然后关键的一步来了
由于脚本是放在Canvas上的,所以我们依然选中输入框(editBox),然后鼠标移动到Canvas上面把Canvas拖入如下位置
拖入Canvas后我们就可以选择canvas下面挂载的脚本了(client脚本)
最后选择我们要接收文本变化事件的函数(就是我们刚才写的函数)
做到这里我们启动一下游戏,看看你在输入框里面输入一下内容,在浏览器里面看看打印信息是否是你输入的信息。
对!你没有看错!到此客户端最关键的一个环节已经完成了。
服务端
到此我们先把手上客户端的活儿放一下!来看看我们的服务端代码(我保证这个比客户端更简单)
还记我们上一节课降到的十行代码吗?
var ws = require("nodejs-websocket");
var server = ws.createServer(function (connect)
{
connect.on("text", function (data) {
console.log('收到消息=',data)
})
connect.on("close", function (code, reason) {});
connect.on("error", function (code, reason) {});
}).listen(3000)
console.log('websocket服务端启动')
我们还是特别的简单在客户端里加上这十行代码。
但是切记要先用npm安装websocket模块,如果你不知道怎么安装不妨移步到我们的上一篇教程。如果你安装了会看到如下的项目结构:
接下来我们来给所有连接到服务端的客户端,注册一个连接(相当于登记了它的身份证号码和可以给它打电话的电话号码,以便我们给这个客户端转发消息)
我们先在此处创建两个变量用来保存连接进来的两个客户端
let client1 = null;
let client2 = null;
接下来我们需要设计一个和客户端沟通的方式,以便区分客户端连接进来的意图(是登录还是平常的发消息)
在这里我们通过json格式简单的设计一个通信协议
{‘name’:'client1','message':'login'}
其中name代表发来消息的人士谁,message代表发来消息的内容,如果内容为login代表是注册否则就是正常的往来消息。
当然因为服务端和客户端之间的消息传递之前都要转换成字符串来传递,所以我们首先需要把收到的消息从json字符串转化为json对象以便我们来拆分需要的信息
let json=JSON.parse(result);//json字符串转对象
let name = json.name;
let message = json.message;
接下来我们先检测一下用户这次发来消息的意图是否是注册
//注册
if(message == 'login')
{
}
然后判断一下是client1注册 还是client2注册,如果是client1注册,我们就让client1 = connect
if(name == 'client1'){
client1 = connect;
console.log('client1注册成功!')
}
细心的朋友应该已经看出来了
client1 = connect;
这行代码就相当于服务端储存了client1这个客户端的电话号码了,后面我们可以用这个connect作为给客户端发送信息的索引。
完整的注册代码如下:
//注册
if(message == 'login')
{
if(name == 'client1'){
client1 = connect;
console.log('client1注册成功!')
}
else if(name == 'client2'){
client2 = connect;
console.log('client2注册成功!')
}
return;
}
到此我们完成了注册的功能,现在可以顺藤摸瓜继续来完成两个客户端通过服务端消息转发的功能(相当于服务端是一个中间的传话人)
在这里我们也简单的规定一个服务端发送消息给客户端的格式
{‘name’:'client2','message','给客户端1请安!'}
我们可以用一个简单的方式来把这个消息封装成一个json对象(姑且起名叫data)
let data = {};
data.name = 'client1';
data.message = json.message;
那么如果我们接收到客户端1发送来的消息就直接转给客户端2,反之亦然
if(name == 'client1'){
let data = {};
data.name = 'client1';
data.message = json.message;
let jsonStr=JSON.stringify(data);//转化成字符串,才能通过服务端转发消息
client2.sendText(jsonStr);//发送消息给客户端2
}
所以总的代码如下:
if(name == 'client1'){
let data = {};
data.name = 'client1';
data.message = json.message;
let jsonStr=JSON.stringify(data);
client2.sendText(jsonStr);
}
else if(name == 'client2'){
let data = {};
data.name = 'client2';
data.message = json.message;
let jsonStr=JSON.stringify(data);
client1.sendText(jsonStr);
}
到这里我们服务端的代码已经全部完成。
回到客户端
我们再次回到客户端把注册和发送消息的逻辑完善
注册
还记得上面我们提到了客户端要给服务端发送消息的约定格式吗
{‘name’:'client1','message':'login'}
于是我们就用一个变量来专门储存当前用户的名字
this.clientName = '';
然后我们用clientName来装载最初用户设置的名字
this.clientName = text;
此时我们给注册按钮绑定一个事件,让点击注册后客户端给服务端发送注册信息。
register(){
//组装消息
let data = {};
data.name = this.clientName;
data.message = 'login';
//转化为字符串发送
let jsonStr=JSON.stringify(data);
//发送
this.ws.send(jsonStr);
}
来到主界面,选中注册按钮,给注册按钮绑定这个事件函数
选中注册按钮ClickEnvents里面添加一个按钮事件,设置如图:
继续选中注册按钮,鼠标点击Canvas不放拖动到ClickEnvents的第一个选项
选择Canvas上绑定的Client脚本
最后选中register脚本
最后加入我们上一节课中的socket连接代码
this.ws = new WebSocket("ws://127.0.0.1:3000");
this.ws.onopen = function (event) {
console.log("连接服务端");
};
this.ws.onmessage = function (event) {
console.log("接收服务端信息: " + event.data);
};
this.ws.onerror = function (event) {
console.log("异常关闭");
};
this.ws.onclose = function (event) {
console.log("断开连接");
};
启动服务端,再启动客户端,输入用户名client1,点击注册!
如果出现如下信息,恭喜!我们的注册系统起效果了。
聊天
接下来我们要实现客户端的聊天功能
首先我们先要再创建一个变量,来判断当前是在注册阶段还是在聊天阶段
this.bRegistered = false;
然后我们在用户点击了注册之后,就可以销毁注册按钮了,同时把状态切换成聊天状态。
为此我们需要把register函数略作改造
register(event, customEventData)
然后调整到聊天模式, 获取当前按钮的节点,最后把注册按钮摧毁。
this.bRegistered = true;//调整到聊天模式
let button = event.target;//获取当前按钮节点
button .destroy();//摧毁按钮
在设置完成状态后我们就保持用户名不变了,同时message变量开始接受用户输入的信息
if(!this.bRegistered)//只有在没有注册时才会有改变用户名
{
this.clientName = text;
}
else {
this.message = text;
}
至此我们可以运行一次项目看看是否注册按钮有顺利的被移除
接下来就是最后一步了!
我们按照之前定义好的消息协议给服务端发送消息。
首先我们为发送按钮定定义一个事件函数
sendMessage(event, customEventData){
//组装消息
let data = {};
data.name = this.clientName;
data.message = this.message;
let jsonStr=JSON.stringify(data);//转化为字符串发送
this.ws.send(jsonStr);//发送
}
然后依葫芦画瓢给“发送按钮”绑定这个函数
最后开启服务端,再开启两个客户端,一个注册名为client1 另外一个注册名为client2
两个客户端都注册成功之后,就可以畅快的发送消息了。
最后一步我们把客户端接收到的对方的消息,显示在label上
我们现在properties处引入Label
messageLabel:cc.Label
然后回到主界面,选中canvas后
把label拖入我们脚本里面的 messageLabel 引用处
最后我们要在接收消息的地方把消息显示到label上
因为在此处回调中,我们无法使用this来找到当前对象,所以我们在start()函数里面定义一个Self变量来代表this
let Self = this;
最后我们稍微把消息做一个处理,就可以给这个label赋值
let json=JSON.parse(event.data);//json字符串转对象
let name = json.name;
let message = json.message;
//拼接最终显示字符串
let str = name+'发来:'+message;
//给label赋值
Self.messageLabel.string = str;
最终代码如下
你最后发送了消息能够在另外一个客户端显示就大功告成了
最后一个小知识Cocos 是可以直接用手机来调试不需要打任何包。
只要你的手机和电脑连接在同一个局域网。
通过微信扫描此处二维码,就可以实现两台手机聊天
当然如果你想用手机连接需要修改一处连接ip
你可以在cmd里面输入
ipconfig
命令
查到自己的ip
用自己的电脑作为服务器,只需要在客户端的代码里把下图处改为你电脑的ip即可
最后:如果你有什么疑问和建议随时欢迎来到群里和我沟通,我将尽快为您解答
本教程所有代码均在github上分享:下载
下一章:叁:极简聊天系统