Jetty 8.1.1 Websocket客户端握手

我正在使用Jetty 8.1.1 Websocket客户端API。
我需要用("Sec-WebSocket-Protocol", "xsCrossfire")("Authorization", "Basic TLVWQMZqRr2hasYnZoI=")更新标题

 WebSocketClientFactory factory = new WebSocketClientFactory(); factory.start(); client = factory.newWebSocketClient(); client.getCookies().put("Sec-WebSocket-Protocol", "xsCrossfire"); client.getCookies().put("Authorization", "Basic TLVWQMZqRr2hasYnZoI="); Future conn = client.open(uri, (WebSocket) this); System.out.printf("Connecting to : %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 

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

一些好消息和一些坏消息。

一,好消息:

要设置Sec-WebSocket-Protocol标头,请使用以下命令。

 client.setProtocol("xsCrossfire"); 

在使用client.open()

接下来,坏消息:

使用Jetty 8.x,您无法设置任意非websocket标头。 这是由于WebSocket的早期实验草案是如何编写的。 根据早期草案规范,您根本不允许设置任意标头,因此Jetty 8.x天后的实现只是不允许它。

然而,随着RFC6455 (官方WebSocket规范)的最终化改变,所有这些更改都被转移到了Jetty 9.x代码库中。 这是100%符合RFC6455的 。 (注意:Jetty 8在服务器端100%兼容RFC6455。Jetty 8在服务器和客户端的RFC6455协议上也是100%兼容的。但是,Jetty 8在客户端只是部分兼容,从function和API的观点。)

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

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

Jetty 9.1 WebSocket客户端的示例

 import java.io.IOException; import java.net.URI; import java.util.concurrent.Future; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; public class ExampleClient { public static class ExampleSocket extends WebSocketAdapter { @Override public void onWebSocketText(String message) { try { // echo the message getRemote().sendString(message); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { try { new ExampleClient().demo(); } catch (Throwable t) { t.printStackTrace(System.err); } } public void demo() throws Exception { WebSocketClient client = new WebSocketClient(); try { client.start(); ClientUpgradeRequest request = new ClientUpgradeRequest(); request.setSubProtocols("xsCrossfire"); request.setHeader("Authorization","Basic TLVWQMZqRr2hasYnZoI="); URI wsUri = URI.create("ws://iltlvl262:8000/echo"); ExampleSocket socket = new ExampleSocket(); Future future = client.connect(socket,wsUri,request); future.get(); // wait for connect socket.getRemote().sendString("hello"); // send message } finally { client.stop(); } } } 

另请注意,从Jetty 9.1开始,甚至完全支持javax.websocket (JSR-356)API。

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

 import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.websocket.ClientEndpoint; import javax.websocket.ContainerProvider; import javax.websocket.OnMessage; import javax.websocket.Session; import javax.websocket.WebSocketContainer; public class ExampleClient { @ClientEndpoint(subprotocols = { "xsCrossfire" }, configurator = ExampleClient.Configurator.class) public static class ExampleSocket { @OnMessage public String onMessage(String msg) { return msg; // echo } } public static class Configurator extends javax.websocket.ClientEndpointConfig.Configurator { @Override public void beforeRequest(Map> headers) { List authvalues = new ArrayList<>(); authvalues.add("Basic TLVWQMZqRr2hasYnZoI="); headers.put("Authorization", authvalues); super.beforeRequest(headers); } } public static void main(String[] args) { try { new ExampleClient().demo(); } catch (Throwable t) { t.printStackTrace(System.err); } } public void demo() throws Exception { WebSocketContainer client = ContainerProvider.getWebSocketContainer(); ExampleSocket socket = new ExampleSocket(); URI wsUri = URI.create("ws://iltlvl262:8000/echo"); Session session = client.connectToServer(socket,wsUri); session.getAsyncRemote().sendText("Hello"); } }