适用于所有社区版。
WebSocket 是 HTML5 开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。在 WebSocket API 中,浏览器和服务器只需要做一次握手的动作,然后浏览器和服务器之间形成一条快速通道,通过快递通道两者之间可以互相传送数据。
Cocos2d-x 引擎集成 libwebsockets,并在 libwebsockets 的客户端 API 基础上封装了一层易用的接口,使得引擎在 C++, JS, Lua 层都能方便的使用 WebSocket 来进行游戏的网络通讯。
创建一个网络连接如下:
local socket = cc.WebSocket:create(url)
网络通信的异步状态回调需要注册事件回调函数:
socket:registerScriptHandler(handlerFunc, eventType)
事件类型有四种:
handlerFunc 需要类型转换处理,后面的示例将展示。
发送数据到服务器:
socket:sendString(str)
客户端可以主动关闭网络连接:
socket:close()
测试 WebSocket,你依然需要自己搭建一个服务器,后面提供了 Golang 编写了一个配套的 WebSocket 服务器 demo 供客户端测试连接。
在 MainScene 中加入如下的代码:
function MainScene:ctor()
self:performWithDelay(function ()
self.socket = cc.WebSocket:create("wss://127.0.0.1:1234")
if self.socket then
self.socket:registerScriptHandler(handler(self, self.onOpen_), cc.WEBSOCKET_OPEN)
self.socket:registerScriptHandler(handler(self, self.onMessage_), cc.WEBSOCKET_MESSAGE)
self.socket:registerScriptHandler(handler(self, self.onClose_), cc.WEBSOCKET_CLOSE)
self.socket:registerScriptHandler(handler(self, self.onError_), cc.WEBSOCKET_ERROR)
end
end, 1.0)
end
function MainScene:onOpen_()
print("onOpen")
self.socket:sendString("Hello server, i'm Quick websocket")
-- delay to close
self:performWithDelay(function () self.socket:close() end, 1.0)
end
function MainScene:onMessage_(message)
print("onMessage:" .. message)
end
function MainScene:onClose_()
print("onClose")
self.socket = nil
end
function MainScene:onError_(error)
print("onError:" .. error)
end
服务器 url 包含ip地址(或域名)和端口号,这里把套接字对象保存到场景中,以便回调函数访问。
registerScriptHandler 注册的事件回调函数,第一个参数需要使用 Quick框架提供的 handler 函数做转换,主要到这里的 self.onOpen_
用的是*点*调用方法,handler 的作用就是让 self 自动传入 self.onOpen_
,以防止出现 “Invalid self” 这样的错误。
注意,我需要收到 cc.WEBSOCKET_OPEN 事件后才能向服务器发送数据。在 MainScene:onOpen_()
中使用 self:performWithDelay
来延迟关闭套接字通道,目的是让前面的 self.socket:sendString()
网络过程走完。
用上面的代码测试我们提供的 golang 服务器,客户端的 log 信息如下:
[WebSocket::init] _host: 127.0.0.1, _port: 1234, _path: /
[1422189039:5365] NOTICE: Initial logging level 7
[1422189039:5365] NOTICE: Library version: 1.3 66b3e53
[1422189039:5365] NOTICE: Started with daemon pid 0
[1422189039:5365] NOTICE: static allocation: 4472 + (16 x 2560 fds) = 45432 bytes
[LUA-print] onOpen
[websocket:send] total: 33, sent: 0, remaining: 33, buffer size: 33
[websocket:send] bytesWrite => 33
[LUA-print] onMessage:Hello client!
websocket (0x7fac80a3cbe0) connection closed by client
connection closing..
[LUA-print] onClose
完整代码如下:
package main
import (
"golang.org/x/net/websocket" // go get github.com/golang/net/websocket
"log"
"net/http"
)
func wsHandler(ws *websocket.Conn) {
var err error
// need loop to keep socket connect
for {
var reply string
if err = websocket.Message.Receive(ws, &reply); err != nil {
log.Printf("connect closed!")
break
}
// client message
println(reply)
if err := websocket.Message.Send(ws, "Hello client!"); err != nil {
log.Printf("Send fail")
}
}
}
func main() {
log.Print("starting socket server ...")
http.Handle("/", websocket.Handler(wsHandler))
if err := http.ListenAndServeTLS(":1234", "cert.pem", "key.pem", nil); err != nil {
// if err := http.ListenAndServe(":1234", nil); err != nil {
log.Fatal("ListenAndServe:", err)
}
}
服务器使用wss方式,需要自签名证书。
在Mac下生成签名证书的命令如下:
$openssl genrsa -out key.pem 2048
$openssl req -new -x509 -key key.pem -out cert.pem -days 3650
由于苹果最新审核要求所有网络请求加入SSL安全链接,Quick社区版从 commit 617427c99760467a7814993a643c91312ad87f00 开始支持 WebSocket 的安全连接。
服务器CA的cert.pem文件需要拷贝到项目工程res下,并改名为”wssca.pem”。引擎会用这个文件作为CA库来验证服务器。