参考:https://www.cnblogs.com/chevin/p/8086999.html
egret写的客户端
//
//
// Copyright (c) 2014-present, Egret Technology.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Egret nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
class Main extends egret.DisplayObjectContainer {
public constructor() {
super();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
}
private onAddToStage(event: egret.Event) {
egret.lifecycle.addLifecycleListener((context) => {
// custom lifecycle plugin
context.onUpdate = () => {
}
})
egret.lifecycle.onPause = () => {
egret.ticker.pause();
}
egret.lifecycle.onResume = () => {
egret.ticker.resume();
}
this.load();
}
private load() {
RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigFinish, this);
RES.addEventListener(RES.ResourceEvent.CONFIG_LOAD_ERROR, this.onConfigError, this);
RES.loadConfig("resource/default.res.json", "resource");
}
private onConfigError(event: RES.ResourceEvent) {
egret.error("onConfigError: event = ", event);
}
private onConfigFinish(event: RES.ResourceEvent) {
RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigFinish, this);
RES.removeEventListener(RES.ResourceEvent.CONFIG_LOAD_ERROR, this.onConfigError, this);
RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS, this.onGroupProgress, this);
RES.addEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onGroupError, this);
RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onGroupFinish, this);
RES.loadGroup("preload");
}
private onGroupProgress(event: RES.ResourceEvent) {
egret.log("onGroupProgress: ", event.itemsLoaded, "/", event.itemsTotal, ", ", event.resItem.name);
}
private onGroupError(event: RES.ResourceEvent) {
egret.log("onGroupError: ", event);
}
private onGroupFinish(event: RES.ResourceEvent) {
RES.removeEventListener(RES.ResourceEvent.GROUP_PROGRESS, this.onGroupProgress, this);
RES.removeEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onGroupError, this);
RES.removeEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onGroupFinish, this);
this.runGame();
}
private runGame() {
let bg: egret.Shape = new egret.Shape();
bg.graphics.beginFill(0x0000ff, 1);
bg.graphics.drawRect(0, 0, GDatas.instance().getStageWidth(), GDatas.instance().getStageHeight());
bg.graphics.endFill();
this.addChild(bg);
let img: egret.Bitmap = new egret.Bitmap();
img.texture = RES.getRes("bg_jpg");
this.addChild(img);
let cSock: CSocket = new CSocket();
cSock.init();
let btnStart: BtnText = new BtnText();
btnStart.refresh(0xFFFF00, "开始");
btnStart.x = GDatas.instance().getStageWidth() / 2;
btnStart.y = 200;
btnStart.touchEnabled = true;
this.addChild(btnStart);
let counter: number = 1;
btnStart.addEventListener(egret.TouchEvent.TOUCH_TAP, (event: egret.TouchEvent) => {
egret.log("click tab ");
cSock.send(String(counter++));
}, this);
}
}
CSocket.ts
class CSocket {
private _socket: egret.WebSocket = null;
private _recvCache: egret.ByteArray = new egret.ByteArray();
private _sendCache: egret.ByteArray = new egret.ByteArray();
private _isConnect: boolean = false;
public constructor() {
}
public init() {
this._socket = new egret.WebSocket();
this._socket.type = egret.WebSocket.TYPE_STRING;
this._socket.addEventListener(egret.Event.CONNECT, this.connect, this);
this._socket.addEventListener(egret.Event.CLOSE, this.close, this);
this._socket.addEventListener(egret.ProgressEvent.SOCKET_DATA, this.receive, this);
this._socket.addEventListener(egret.IOErrorEvent.IO_ERROR, this.ioError, this);
this._socket.connectByUrl("ws://127.0.0.1:18993/echo");
}
private connect(event: egret.Event) {
egret.log("connect ");
this._isConnect = true;
}
private close(event: egret.Event) {
egret.log("close");
this._isConnect = false;
}
private ioError(event: egret.Event) {
egret.log("ioError");
}
private receive(event: egret.Event) {
this._recvCache.clear();
// this._socket.readBytes(this._recvCache);
let buf: string = this._socket.readUTF();
egret.log("recieve : buf = ", buf, ", \n");
}
public send(text: string) {
this._sendCache.clear();
this._socket.writeUTF(text);
this._socket.flush();
}
}
服务器:
package main
import (
"fmt"
"net/http"
"os"
"time"
"golang.org/x/net/websocket"
)
//错误处理函数
func checkErr(err error, extra string) bool {
if err != nil {
formatStr := " Err : %s\n"
if extra != "" {
formatStr = extra + formatStr
}
fmt.Fprintf(os.Stderr, formatStr, err.Error())
return true
}
return false
}
func svrConnHandler(conn *websocket.Conn) {
request := make([]byte, 128)
defer conn.Close()
for {
readLen, err := conn.Read(request)
if checkErr(err, "Read") {
break
}
//socket被关闭了
if readLen == 0 {
fmt.Println("Client connection close!")
break
} else {
//输出接收到的信息
fmt.Println(string(request[:readLen]))
time.Sleep(time.Second)
//发送
conn.Write([]byte("World !"))
}
request = make([]byte, 128)
}
}
func main() {
http.Handle("/echo", websocket.Handler(svrConnHandler))
err := http.ListenAndServe(":18993", nil)
checkErr(err, "ListenAndServe")
fmt.Println("Func finish.")
}
客户端
package main
import (
"fmt"
"os"
"sync"
"golang.org/x/net/websocket"
)
var gLocker sync.Mutex //全局锁
var gCondition *sync.Cond //全局条件变量
var origin = "http://127.0.0.1:18993/"
var url = "ws://127.0.0.1:18993/echo"
//错误处理函数
func checkErr(err error, extra string) bool {
if err != nil {
formatStr := " Err : %s\n"
if extra != "" {
formatStr = extra + formatStr
}
fmt.Fprintf(os.Stderr, formatStr, err.Error())
return true
}
return false
}
//连接处理函数
func clientConnHandler(conn *websocket.Conn) {
gLocker.Lock()
defer gLocker.Unlock()
defer conn.Close()
request := make([]byte, 128)
for {
readLen, err := conn.Read(request)
if checkErr(err, "Read") {
gCondition.Signal()
break
}
//socket被关闭了
if readLen == 0 {
fmt.Println("Server connection close!")
//条件变量同步通知
gCondition.Signal()
break
} else {
//输出接收到的信息
fmt.Println(string(request[:readLen]))
//发送
conn.Write([]byte("Hello !"))
}
request = make([]byte, 128)
}
}
func main() {
conn, err := websocket.Dial(url, "", origin)
if checkErr(err, "Dial") {
return
}
gLocker.Lock()
gCondition = sync.NewCond(&gLocker)
_, err = conn.Write([]byte("Hello !"))
go clientConnHandler(conn)
//主线程阻塞,等待Singal结束
for {
//条件变量同步等待
gCondition.Wait()
break
}
gLocker.Unlock()
fmt.Println("Client finish.")
}