Java使用WebSocket
0
之前有一篇WebSocket
的视频通话教程,那个主要不是讲怎么使用WebSocket
,这篇文章主要就说一下WebSocket
的使用。
首先要用到的是最新的Tomcat8
,因为要支持JavaEE7
,JavaEE7
把WebSocket
纳入规范的。
下面是代码:
@ServerEndpoint("/face/accept/{rid}")
public class FaceSocket {
@OnOpen
public void onOpen(Session session, @PathParam("rid") String rid) {
// 打开一个websocket时调用方法,上面的注解有点类似springMVC
session.getAsyncRemote().sendText("逗比你好!");
}
@OnClose
public void onClose(Session session, @PathParam("rid") String rid) {
// 关闭时调用方法,这个方法好像存在问题,而且不要手动关闭session
}
@OnMessage
public void onMessage(String message, Session session, @PathParam ("rid")String rid) {
// 接受到消息时调用方法,session就是用户的session,message就是接受到的用户的信息
session.getAsyncRemote().sendText(message);
}
}
这里要说一下上面的onClose
方法,这个方法里面:
- 不要使用
session
发送消息给用户 - 不要手动调用
close
方法 - 不能有任何异常抛出
以上三种情况都会引起
Message will not be sent because the WebSocket session has been closed
,后来发现升级到Tomcat9
后就没有上面的错误了,估计应该是Tomcat8
的BUG。
下面是JS部分(使用sender
的send
方法就可以发送消息了):
var sender;
function initWebSocket(url) {
if(!WebSocket) {
alert("你的浏览器不支持WebSocket!");
return null;
}
var webSocket = new WebSocket(url);
webSocket.onerror = function(event) {
console.log("websocket发送错误:" + event.data);
}
webSocket.onopen = function(event) {
console.log("websocket打开");
}
webSocket.onclose = function(event) {
console.log("websocket关闭");
}
webSocket.onmessage = function(event) {
// websocket收到消息
var message = JSON.parse(event.data);
logMessage(message.content, true);
}
sender = {
send : function(message) {
// 调用websocket的发送
webSocket.send(message);
}
}
}
URL的格式:ws://域名/face/accept/rid
17-Apr-2018 11:59:37.595 严重 [http-nio-8080-exec-5] org.apache.tomcat.websocket.pojo.PojoEndpointBase.onError No error handling configured for [com.acgist.web.websocket.AcgistVideo] and the following error occurred
java.io.EOFException
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1167)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1107)
这个错误时没有添加@OnError
这个处理方法导致的。
如果经常出现EOFException
,可以检查Nginx配置:
proxy_read_timeout 1200s;
keepalive_timeout 1200s;
参考:https://www.codeleading.com/article/12972598394/
事实证明依然存在问题。
如果提示:
The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method
这个问题之前使用异步发送,改为同步发送暂时就没有发现问题了:
synchronized (session) {
try {
session.getBasicRemote().sendText(message);
// session.getAsyncRemote().sendText(message);
} catch (IOException e) {
LOGGER.error("WebSocket发送异常:{}", message, e);
}
}