Jetty 8.1.1 Websocket客户端握手

Tom*_*ein 4 java jetty 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<Connection> conn = client.open(uri, (WebSocket) this);
System.out.printf("Connecting to : %s%n", uri);
Run Code Online (Sandbox Code Playgroud)

请求看起来:

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
Run Code Online (Sandbox Code Playgroud)

预期要求:

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
Run Code Online (Sandbox Code Playgroud)

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

Joa*_*elt 7

一些好消息和一些坏消息.

一,好消息:

要设置Sec-WebSocket-Protocol标题,请使用以下内容.

client.setProtocol("xsCrossfire");
Run Code Online (Sandbox Code Playgroud)

在你使用之前 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在客户端只是部分兼容,从功能和API的观点.)

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

从Jetty 9.x开始,所有旧的websocket实验草稿都被删除,只留下RFC6455支持,这使得Jetty可以打开更多以前不允许的功能.这包括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<Session> future = client.connect(socket,wsUri,request);

            future.get(); // wait for connect

            socket.getRemote().sendString("hello"); // send message
        }
        finally
        {
            client.stop();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另请注意,从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<String, List<String>> headers)
        {
            List<String> 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");
    }
}
Run Code Online (Sandbox Code Playgroud)