我正在使用Jetty 9.3.5并且我想知道在发送websocket消息时处理不可靠连接的正确方法是什么,具体来说:我注意到当websocket连接没有正常关闭时的情况,即使客户端在服务器上触发onClose()需要花费很多时间(例如,用户关闭笔记本电脑盖并将其置于待机状态 - 可能需要1-2小时才能收到关闭事件服务器端)。
因此,由于客户端仍然注册,服务器会不断发送开始构建的消息。发送大量邮件时,这会成为一个问题。
我已经测试过发送字节消息:
Session.getRemote().sendBytes(ByteBuffer, WriteCallback)
Session.getRemote().sendBytesByFuture(ByteBuffer);
要模拟一侧的连接(即用户将笔记本电脑置于待机状态),在Linux上,我为eth0接口分配了一个IP地址,开始发送消息然后将其关闭:
ifconfig eth0 192.168.1.1
ifconfig eth0 up
--- start sending messages (simple incremented numbers) and connect using Chrome browser and print them ---
ifconfig eth0 down
这样:Jetty仍在发送邮件,Chrome客户端没有收到邮件,服务器端没有触发onCllose或onError
关于Jetty的问题是:
有没有办法清除未送达的排队邮件? 我试过了,但没有运气:
Session.getRemote()平齐();
可以设置最大排队消息数吗? 我试过了:
WebSocketServletFactory.getPolicy()。setMaxBinaryMessageBufferSize(1)
我可以检测客户端是否收不到该消息吗? (或者,如果连接处于异常状态,请说) 我试过了:
session.getRemote().sendBytes(bb, new WriteCallback() {
@Override
public void writeSuccess() {
//print success }
@Override
public void writeFailed(Throwable arg0) {
//print fail
}
});
但即使没有收到消息,这也会成功。
我也尝试使用,但找不到解决方案:
factory.getPolicy().setIdleTimeout(...);
factory.getPolicy().setAsyncWriteTimeout(3000);
sendPing()
提前致谢!
答案 0 :(得分:1)
不幸的是,作为消息传递协议的WebSocket协议实际上并不是为消息之间的这种细微差别而设计的。
在您甚至可以考虑发送下一条消息之前,必须先完成第一条消息。因此,如果您正在处理消息,则无法安全地取消该消息。
充其量,可以使用API来截断该消息,并使用CONTINUATION / empty payload / fin = true。
但即便如此,远程端点也不会知道您取消了该消息,它只会看到部分消息。
检测连接问题最好使用操作系统级事件(如Android的连接意图),或通过定期websocket PING(将其自身插入到传输websocket框架的行前面。
但是,即使使用PING,如果你的传出websocket框架正在进行中,那么即使在完成发送websocket框架之前也不能发送PING。
RemoteEndpoint.flush()
将尝试刷新任何待处理的消息(和帧),而不是清除待处理的消息(或帧)。
至于检测客户端是否收到消息,您需要在自己的层中实现某种消息ACK以验证协议没有这样的概念。 (构建在websocket之上的一些libs / apis已经在该层中实现了消息ACK。cometd message ack extension作为一个真实世界的例子浮现在脑海中。
您试图解决什么样的情况?
也许使用RemoteEndpoint.sendPartialString(String, boolean)
或RemoteEndpoint.sendPartialBytes(ByteBuffer, boolean)
发送整个邮件的较小帧可能对您有用。但是,另一方可能没有可以读取这些部分帧的API(例如:浏览器中的Javascript)。