我想在webapp中使用WebSocket。我正在使用Eclipse(Mars.2版本4.5.2)来运行Tomcat 7.0.77实例。它在部署到独立的Tomcat实例时有效,但在Tomcat在Eclipse中运行时则无效。
我也尝试过Tomcat 8.0.43,结果相同。
在Eclipse中,当onMessage方法调用sendText方法时,总是抛出java.net.SocketException,并显示消息“Connection reset by peer:socket write error”,并且调用浏览器的onclose函数。
我有一个基本的终点:
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/echo")
public class EchoServer {
@OnOpen
public void onOpen(Session session) {
System.out.println("onOpen: " + session.getId());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("onMessage: " + session.getId() + ", " + message);
try {
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
@OnClose
public void onClose(Session session) {
System.out.println("onClose: " + session.getId());
}
}
和一个简单的测试用户界面:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket test</title>
<script type="text/javascript">
var Example = {
socket: undefined,
open: function() {
this.socket = new WebSocket("ws://" + window.location.host + "/echo/echo");
this.socket.onopen = function() {
console.log("onopen");
};
this.socket.onmessage = function(e) {
document.getElementById("message").innerText = e.data;
};
this.socket.onclose = function() {
console.log("onclose");
};
},
send: function(message) {
this.socket.send(message);
}
}
Example.open();
</script>
</head>
<body>
<div id="message"></div>
<button onclick="Example.send('Hello world')">Send</button>
</body>
</html>
单击UI按钮时,消息将发送到端点。然后,端点使用getBasicRemote().sendText(message)
将消息发送回UI。
在Eclipse中,Tomcat会抛出以下异常:
java.io.IOException: java.util.concurrent.ExecutionException: java.net.SocketException: Connection reset by peer: socket write error
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:286)
at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:572)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:466)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.onError(WsHttpUpgradeHandler.java:161)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.access$300(WsHttpUpgradeHandler.java:47)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onError(WsHttpUpgradeHandler.java:225)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:208)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:203)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:93)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:635)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.concurrent.ExecutionException: java.net.SocketException: Connection reset by peer: socket write error
at org.apache.tomcat.websocket.FutureToSendHandler.get(FutureToSendHandler.java:120)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:281)
... 14 more
Caused by: java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at org.apache.coyote.http11.upgrade.BioServletOutputStream.doWrite(BioServletOutputStream.java:38)
at org.apache.coyote.http11.upgrade.AbstractServletOutputStream.writeInternal(AbstractServletOutputStream.java:153)
at org.apache.coyote.http11.upgrade.AbstractServletOutputStream.write(AbstractServletOutputStream.java:121)
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:94)
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:456)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:344)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:276)
... 14 more
然后立即关闭WebSocket,并触发onClose
。我使用的是Chrome 57和MS Edge 38。
这是一个已知的Eclipse问题,还是我的测试代码做了一些愚蠢的事情?感谢。
更新
这不是Eclipse问题。当它们在端口8080上运行时,它发生在包含Eclipse的Tomcat和独立的Tomcat中。如果我更改端口(我使用7777),那么它可以工作。我已经改变了这个问题的标题以反映这一点。
更新
看起来这是一个阻止端口80和8080上的WebSockets的防火墙/代理问题。抱歉,这不是问题。