Java Jetty 8.1.1 Websocket客户端握手

Java Jetty 8.1.1 Websocket客户端握手,java,websocket,jetty,Java,Websocket,Jetty,我正在使用Jetty 8.1.1 Websocket客户端api。 我需要用(“Sec WebSocket协议”,“xsCrossfire”)和(“授权”,“基本TLVWQMZqRr2hasYnZoI=”)更新标题。 WebSocketClientFactory=newWebSocketClientFactory(); factory.start(); client=factory.newWebSocketClient(); client.getCookies().put(“Sec WebSoc

我正在使用Jetty 8.1.1 Websocket客户端api。
我需要用
(“Sec WebSocket协议”,“xsCrossfire”)
(“授权”,“基本TLVWQMZqRr2hasYnZoI=”)更新标题。

WebSocketClientFactory=newWebSocketClientFactory();
factory.start();
client=factory.newWebSocketClient();
client.getCookies().put(“Sec WebSocket协议”、“xsCrossfire”);
client.getCookies().put(“授权”,“基本TLVWWQMZQRR2HASYNZOI=”);
Future conn=client.open(uri,(WebSocket)this);
System.out.printf(“连接到:%s%n”,uri);
请求外观:

Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Cookie: Sec-WebSocket-Protocol=xsCrossfire\r\n
Cookie: Authorization="Basic TLVWQMZqRr2hasYnZoI="\r\n
Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Sec-WebSocket-Protocol: xsCrossfire\r\n
Authorization: "Basic TLVWQMZqRr2hasYnZoI="\r\n
预期请求:

Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Cookie: Sec-WebSocket-Protocol=xsCrossfire\r\n
Cookie: Authorization="Basic TLVWQMZqRr2hasYnZoI="\r\n
Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Sec-WebSocket-Protocol: xsCrossfire\r\n
Authorization: "Basic TLVWQMZqRr2hasYnZoI="\r\n

如何在8.1.1版中正确实现握手?

一些好消息和一些坏消息

首先,好消息:

Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Cookie: Sec-WebSocket-Protocol=xsCrossfire\r\n
Cookie: Authorization="Basic TLVWQMZqRr2hasYnZoI="\r\n
Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Sec-WebSocket-Protocol: xsCrossfire\r\n
Authorization: "Basic TLVWQMZqRr2hasYnZoI="\r\n
要设置
Sec WebSocket协议
标题,请使用以下命令

client.setProtocol("xsCrossfire");
在使用
client.open()之前

接下来是坏消息:

Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Cookie: Sec-WebSocket-Protocol=xsCrossfire\r\n
Cookie: Authorization="Basic TLVWQMZqRr2hasYnZoI="\r\n
Host: iltlvl262:8000\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: FHKTsICO2vqGCxXVwLkH4Q==\r\n
Sec-WebSocket-Protocol: xsCrossfire\r\n
Authorization: "Basic TLVWQMZqRr2hasYnZoI="\r\n
使用Jetty 8.x,您无法设置任意非websocket标头。这是由于WebSocket的早期实验草稿是如何编写的。根据早期的规范草案,您根本不允许设置任意的头,因此Jetty8.x版本中的实现就不允许这样做

然而,随着(官方WebSocket规范)的最终确定,所有这些更改都被应用到Jetty9.x代码库中。这是100%符合。(注意:Jetty 8在服务器端100%兼容RFC6455。Jetty 8在服务器和客户端使用的RFC6455协议上也100%兼容。但是,从功能和API的角度来看,Jetty 8在客户端仅部分兼容。)

Jetty 7和Jetty 8的决定是为了保留旧的实验草案,以供那些早期采用者和仍然使用它们的旧浏览器(Safari 5.x)使用。这一决定阻止我们允许旧实验草案中特别禁止的行为

从Jetty 9.x开始,所有旧的websocket实验草稿都被删除,只剩下支持,这使得Jetty能够打开更多以前不允许的功能。这包括WebSocketClient上的任意头

Jetty 9.1 WebSocket客户端示例

import java.io.IOException;
导入java.net.URI;
导入java.util.concurrent.Future;
导入org.eclipse.jetty.websocket.api.Session;
导入org.eclipse.jetty.websocket.api.WebSocketAdapter;
导入org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
导入org.eclipse.jetty.websocket.client.WebSocketClient;
公共类示例客户端
{
公共静态类ExampleSocket扩展WebSocketAdapter
{
@凌驾
WebSockettext上的公共void(字符串消息)
{
尝试
{
//回应信息
getRemote().sendString(消息);
}
捕获(IOE异常)
{
e、 printStackTrace();
}
}
}
公共静态void main(字符串[]args)
{
尝试
{
新示例client().demo();
}
捕获(可丢弃的t)
{
t、 printStackTrace(System.err);
}
}
public void demo()引发异常
{
WebSocketClient=新的WebSocketClient();
尝试
{
client.start();
ClientUpgradeRequest=新的ClientUpgradeRequest();
请求。设置子协议(“xsCrossfire”);
request.setHeader(“授权”,“基本TLVWQMZqRr2hasYnZoI=”);
uriwsuri=URI.create(“ws://iltlvl262:8000/echo”);
ExampleSocket=新的ExampleSocket();
Future=client.connect(套接字、wsUri、请求);
future.get();//等待连接
socket.getRemote().sendString(“hello”);//发送消息
}
最后
{
client.stop();
}
}
}
还要注意的是,从Jetty 9.1开始,甚至(JSR-356)API都得到了完全支持

在Jetty 9.1上使用javax.websocket的相同示例

导入java.net.URI;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.Map;
导入javax.websocket.ClientEndpoint;
导入javax.websocket.ContainerProvider;
导入javax.websocket.OnMessage;
导入javax.websocket.Session;
导入javax.websocket.WebSocketContainer;
公共类示例客户端
{
@ClientEndpoint(subtocols={“xsCrossfire”},
configurator=ExampleClient.configurator.class)
公共静态类ExampleSocket
{
@OnMessage
消息上的公共字符串(字符串消息)
{
return msg;//echo
}
}
公共静态类配置器
扩展javax.websocket.ClientEndpointConfig.Configurator
{
@凌驾
请求前公共无效(映射头)
{
List authvalues=new ArrayList();
添加(“基本TLVWQMZqRr2hasYnZoI=”);
headers.put(“授权”,authvalues);
super.beforeRequest(标题);
}
}
公共静态void main(字符串[]args)
{
尝试
{
新示例client().demo();
}
捕获(可丢弃的t)
{
t、 printStackTrace(System.err);
}
}
public void demo()引发异常
{
WebSocketContainer客户端=ContainerProvider.getWebSocketContainer();
ExampleSocket=新的ExampleSocket();
uriwsuri=URI.create(“ws://iltlvl262:8000/echo”);
会话=client.connectToServer(socket,wsUri);
session.getAsyncRemote().sendText(“Hello”);
}
}

Hi Erdfelt,感谢您的详细解释。我切换到Jetty 9,但出现以下异常:java.lang.UnsupportedClassVersionError:org/eclipse/Jetty/websocket/api/WebSocke