web socket数据接受和发送处理

网络中一条完整的消息如下:
4字节—4字节-----4字节----------4字节-----------4字节(消息头)---------n字节(消息实体)
总长度—id--------低字节序------高字节序--------session---------------------实体
原理
简单来说,WebSocket是一种协议,与HTTP协议一样位于应用层,都是TCP/IP协议的子集。HTTP协议是单向通信协议,只有客户端发起HTTP请求,服务端才会返回数据。而WebSocket协议是双向通信协议,在建立连接之后,客户端和服务器都可以主动向对方发送或接受数据。WebSocket协议建立的前提需要借助HTTP协议,建立连接之后,持久连接的双向通信就与HTTP协议无关了

底层的socket

消息和具有五个属性的消息头(PackHead),组成一个发送包或者接收包,这个包在网络上传输,五个属性(消息的长度,消息id,低字节序,高字节序,session),每个属性占4个字节;
DataView:数据视图
Byte:每一个单独的消息都有它来管理
u8d:Uint8Array
d:DataView
pos:当前操作字节流的位置
length:缓冲区的长度
bytesAvailable:可从字节流的当前位置到末尾读取的数据的字节数
填充函数writeArrayBuffer():往缓冲里写入数组数据
填充函数writeUint32(value: number):往缓冲里写入数据
填充函数writeUint16(value: number):往缓冲里写入数据
填充函数writeUint8(value: number):往缓冲里写入数据
取出函数readArrayBuffer():从缓冲里取出数组数据
取出函数readUint32(value: number):往缓冲里取出数据
取出函数readUint16(value: number):往缓冲里取出数据
取出函数readUint8(value: number):往缓冲里取出数据

其实就是对于一个缓冲区的读取操作,至于如何读取,下面的api也给的很全面
这里就不全部展示了
PackHead:
socket: 发送包(encode):_output
生成一个消息头+消息主体,然后发送,消息头占20个字节,所以消息的长度=真实消息的长度 +20,消息头:往缓冲中每四个字节依次写入消息的长度,消息id,低字节序,高字节序,session,这个五个属性,最后再写入消息
socket:接受包(decode):_input
解析消息的时候,也是收到发来数据时候,先获得消息的长度,建立缓冲区,然后往这个缓冲区里写入数据,直到写满这个长度的消息数据,才算这个消息接受完毕,最后才分发出去,这样可以防止占包,
字节处理类:Byte.js,套接字处理类:Socket.js
地址
提取码:p78r

心跳服务

内部有一个定时器,负责一定时间向服务器发送一遍数据,内部也有一个监听服务器消息的函数,每次收到服务器的消息,就记录一下时间,判断是否还存活的标志就是用当前时间减去最近一次接受服务器的时间,如果这个差值大于我们设定的一个值比如2秒,那么就认为超时了,可以做超时处理

请求服务

内部存储和管理所有的请求_requestList:
内部注册一个监听服务器消息的函数,每次收到消息就和自己的请求队列去比对,看是哪个请求的消息回来了
一个单独的请求Request
消息发送Id;
消息msg:
消息的回复id:
消息的发送时间:
消息的检查时间:
是否发送:
是否回复:
send():调用此函数发送数据
checkResponse(responseId):判断回复的数据是否为当前的消息
isTimeout():判断请求消息是否超时:
isWaiting():判断请求的消息是否还在等待中;

网络管理员:

send(id, buff);传入消息的id,和一个object,此处会对这个buff进行protobuf encode处理生成一个新的buf,
然后将消息加入到请求队列中,触发消息发送flush;
_onRecvMessage(msgId, msgBuf, msgLen):收到socket管理员传来的一个消息,此处会进行protobuf解析,然后分发出去

//将协议文件读入内存
cc.loader.loadRes("proto/cs", cc.TextAsset, (err, res: cc.TextAsset) => {
            this.loadProtoComplete(err, res, callback);
        });
private loadProtoComplete(err, res: any, callback: Function) {
        if (err) {
            return;
        }
        this.setProtobufRes(res);
        callback();
    }
private setProtobufRes(res: any) {
     let protobuf = window['dcodeIO'].ProtoBuf;
     if (protobuf == null) {
         return;
     }
     this._pbc = protobuf.loadProto(res, 'proto/cs').build('cs');
     // this._pbc = new protobuf.Root();
     // protobuf.parse(res, this._pbc, { keepCase: true });
 }
//加密probuf
public encodeProtoBuff(id, buff) {
        let protoId: string = MessageConst["cs" + id];
        let proto = new this._pbc[protoId.substr(3)];
        for (let i in buff) {
            proto[i] = buff[i];
        }
        return proto.toArrayBuffer();
    }
public _onRecvMessage(msgId, msgBuf, msgLen) {
        let cs = MessageConst["cs" + msgId]
         //解密protobuf
        let proto = this._pbc[cs.substr(3)]
        let buff = proto.decode(msgBuf)
        this.logReceiveNet(msgId, buff);
        if (buff) {
            let convtbuff = buff //this:_metatableTransToTable(buff)
            if (convtbuff.ret) {
                if (NetworkManager.FILTER_LIST_RET[msgId] == null) {
                    this._onMessageError(convtbuff.ret)
                }
            }
            //
            this._receiveSignal.dispatch(msgId, convtbuff)
            //
            let key = "signal_" + msgId;
            let signal = this._signals[key]
            if (signal) {
                signal.dispatch(msgId, convtbuff)
            }
        }
    }

socket管理员:

接管底层socket,连接服务器,断开服务器,负责发送消息,接受消息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值