包头:
public setSession(userId: number, sessionId: number) {
this.userId = userId;
this.uidH32 = Math.floor(this.userId / (Math.pow(2, 32)));
this.uidL32 = this.userId % (Math.pow(2, 32));
this.sessionId = sessionId;
}
class PackHead {
public packLength: number = 0; //包的长度
public msgLength: number = 0; //消息的长度
public cmd: number = 0; //消息id
public uidH32: number = 0; //userid的一个取除值 详见setSession
public uidL32: number = 0; //userid的一个取模值 详见setSession
public sid: number = 0; //sessionID
//生成一个包头
public encode(msgLength: number, cmd: number, uidH32: number, uidL32: number, sid: number): ArrayBuffer {
this.msgLength = msgLength;
this.packLength = this.msgLength + 20; //一个包的长度等于实际消息的长度+包头的长度20个字节
this.cmd = cmd;
this.uidH32 = uidH32;
this.uidL32 = uidL32;
this.sid = sid;
let bytes = new Byte();
bytes.endian = Byte.BIG_ENDIAN;
bytes.writeUint32(this.packLength); //4个字节
bytes.writeUint32(this.cmd); //4个字节
bytes.writeUint32(this.uidH32); //4个字节
bytes.writeUint32(this.uidL32); //4个字节
bytes.writeUint32(this.sid); //4个字节
bytes.pos = 0;
return bytes.readArrayBuffer(bytes.length)
}
//分解包头
public decode(byte: Byte): Byte {
this.packLength = byte.getUint32();
this.msgLength = this.packLength - 20;
this.cmd = byte.getUint32();
this.uidH32 = byte.getUint32();
this.uidL32 = byte.getUint32();
this.sid = byte.getUint32();
return byte;
}
}
接受消息
/**
* <p>连接到指定的主机和端口。</p>
* <p>连接成功派发 Event.OPEN 事件;连接失败派发 Event.ERROR 事件;连接被关闭派发 Event.CLOSE 事件;接收到数据派发 Event.MESSAGE 事件; 除了 Event.MESSAGE 事件参数为数据内容,其他事件参数都是原生的 HTML DOM Event 对象。</p>
* @param host 服务器地址。
* @param port 服务器端口。
*/
connect(): void {
if (this._isConnected) {
return;
}
let url: string = this._host + ":" + this._port;
if (!this.protocols || this.protocols.length == 0) {
this._socket = new window.WebSocket(url);
} else {
this._socket = new window.WebSocket(url, this.protocols);
}
this._socket.binaryType = "arraybuffer";
this._output = new Byte();
this._output.endian = this.endian;
this._input = new Byte();
this._input.endian = this.endian;
this._addInputPosition = 0;
this._socket.onopen = (e: any) => {
this._onOpen(e);
};
this._socket.onmessage = (msg: any): void => {
this._onMessage(msg);
};
this._socket.onclose = (e: any): void => {
this._onClose(e);
};
this._socket.onerror = (e: any): void => {
this._onError(e);
};
}
/**
* @private
* 接收到数据处理方法。
* @param msg 数据。
*/
protected _onMessage(msg: any): void {
// console.log("[Socket] _onMessage",msg.data.byteLength);
if (!msg || !msg.data) return;
var data: any = msg.data;
if (this._input.length > 0 && this._input.bytesAvailable < 1) {
this._input.clear();
this._addInputPosition = 0;
}
var pre: number = this._input.pos;
!this._addInputPosition && (this._addInputPosition = 0);
this._input.pos = this._addInputPosition;
if (data) {
if (typeof (data) == 'string') {
this._input.writeUTFBytes(data);
} else {
this._input.writeArrayBuffer(data);
}
this._addInputPosition = this._input.pos;
this._input.pos = pre;
this._onMessageDecode();
}
}
private _onMessageDecode() {
let packHead: PackHead = new PackHead();
this._input = packHead.decode(this._input);
let message: any = this._input.getUint8Array(this._input.pos, this._input.length)
this._dispatchMessageHandler(packHead.cmd, message, packHead.msgLength);
}
发送消息
先往缓冲中写入20个字节的包头,紧跟着,再往缓冲中写消息字节
/**
* 发送数据到服务器。
* @param data 需要发送的数据,可以是String或者ArrayBuffer。
*/
send(id: number, msg: any): void {
let packHead: PackHead = new PackHead();
let packHeadArrayBuffer: ArrayBuffer = packHead.encode(msg.byteLength, id, this.uidH32, this.uidL32, this.sessionId);
this._output.writeArrayBuffer(packHeadArrayBuffer, 0, packHeadArrayBuffer.byteLength);
this._output.writeArrayBuffer(msg);
this.flush();
}
本文详细介绍了WebSocket通信协议的使用,包括设置用户标识、会话ID,以及消息的编码和解码过程。通过创建包头类`PackHead`,实现了消息的打包和解包,确保了数据在客户端与服务器之间的正确传输。此外,还展示了WebSocket连接的建立、数据接收与发送的方法,强调了数据的类型处理和事件监听。
154

被折叠的 条评论
为什么被折叠?



