一、前言

最近在把后台Golang版的WebSocket项目修改为Java版的WebSocket项目;由于没有Golang的代码,只能自己想办法硬猜该怎么写。

在踩了一堆坑后,终于基本写完了。以下是踩坑总结与解决办法。

二、问题描述

1.前后台的WebSocket通信,传递的是字节数组(byte[]),而不是String。

2.因此,后台使用wsSession.getAsyncRemote().sendText(string)给前台发送消息的话,前台会报错,无法解析。

3.后台尝试用ByteBuffer对象装入需要发送的消息,使用wsSession.getAsyncRemote().sendBinary(byteBuffer)发送给前台消息,但是前台vconsole中没有任何反应,似乎是没有收到消息。

4.后台尝试增加wsSession.getAsyncRemote().flushBatch()方法,这个方法看起来类似flush()方法,但是会报错,不能使用。

5.后台尝试使用wsSession.getBasicRemote().sendBinary(byteBuffer)方法,但是前台vconsole还是没有反应,似乎是没有收到消息。

6.后台尝试增加wsSession.getBasicRemote().flushBatch()方法,这个方法看起来类似BasicRemote的flush()方法,但是会报错,还是不能使用。

7.后台发现,如果用getBasicRemote()的话,可以拿到输出流对象,OutputStream os = wsSession.getBasicRemote().getSendStream()

8.于是,后台这样写,但是前端还是收不到消息:

OutputStream os = wsSession.getBasicRemote().getSendStream();
os.write(byteBuffer.array());
os.flush();

三、解决办法

经过多次尝试发现,Java发送webSocket的字节数组信息给前端时,只增加flush()是不够的,必须增加close(),前端才能收到消息。代码样例如下:

OutputStream os = wsSession.getBasicRemote().getSendStream();
os.write(byteBuffer.array());
os.flush();
os.close();

四、总结

1.Java通过WebSocket发送消息给前端,网上一般用这个方法:

wsSession.getAsyncRemote().sendText(string);

发送String类型的消息应该没有问题,但是如果用类似的方法wsSession.getAsyncRemote().sendBinary(byteBuffer);,发送字节数组时,就会有问题,前端总是收不到消息(不知道怎么flush)。

2.经过测试,如果要给前端发送字节数组,最好还是用OutputStream os = wsSession.getBasicRemote().getSendStream()获得BasicRemote的输出流(AsyncRemote无法获得输出流),然后write()写消息,最后close()关闭流,前端就可以收到消息了。

五、其它

虽然没有Golang代码,但是还好有前端的js代码,通过查看js代码梳理出了主要流程,然后用Java实现了之前Golang的WebSocket的功能。

以下是js相关总结:
1.then()方法,会在上一个方法执行完毕后,才执行then()方法中的内容。

2.对于Promise方法,如果其后有then方法,那么只有当Promise方法的resolve()方法被执行,才说明Promise方法执行完毕,才会走后续的then方法。

3.如果Promise方法的reject()方法被执行,那么会报错,不会继续走then()方法;如果外层有try-catch,那么就会进入catch方法。

4.如果Promise方法的resolve(o)方法中包含参数o,那么这个参数o可以传递给后续的then方法。

5.Promise.race方法的意思是,其中可以写一个方法数组,这个方法数组中可以有多个方法,这些方法都会执行,采用赛跑(race)模式,如果哪个方法先执行完毕,就采用这个方法的结果。

6.关于EventEmitter,可以使用.on(key,function)方法注册一个触发器;后续使用.emit(key,obj)方法,可以触发key一致的function方法,obj则可以当做参数传递给function方法。

7.js中,websocket的消息监听方法样例为

this.websocket.addEventListener('message',this._function);

如果用到了websocket,总是可以搜索到这一句的(外面找不到的话,可以找找node_modules里面)。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐