4

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);

リクエストは次のようになります。

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 でハンドシェイクを正しく実装するにはどうすればよいですか?

4

1 に答える 1

7

良いニュースと悪いニュースがあります。

まず、良いニュース:

Sec-WebSocket-Protocolヘッダーを設定するには、次を使用します。

client.setProtocol("xsCrossfire");

ご使用前にclient.open()

次に、悪いニュース:

Jetty 8.x では、任意の非 WebSocket ヘッダーを設定できません。これは、WebSocket の初期の実験的なドラフトがどのように作成されたかによるものです。初期のドラフト仕様では、任意のヘッダーを設定することは許可されていなかったため、Jetty 8.x 時代の実装では許可されていませんでした。

ただし、RFC6455 (公式の WebSocket 仕様) の最終決定により変更が加えられたため、これらの変更はすべて Jetty 9.x コードベースに組み込まれました。RFC6455に 100%準拠しています。 (注: Jetty 8 は、サーバー側で RFC6455 に 100% 準拠しています。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();
        }
    }
}

また、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");
    }
}
于 2013-11-04T19:20:47.410 に答える