All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.grizzly.websockets.WebSocketClient Maven / Gradle / Ivy

package com.sun.grizzly.websockets;

import com.sun.grizzly.tcp.http11.Constants;
import com.sun.grizzly.util.net.URL;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.logging.Level;

public class WebSocketClient extends BaseWebSocket implements WebSocket {
    private SocketChannel channel;

    private static final String CLIENT_HANDSHAKE = "GET /echo HTTP/1.1" + Constants.CRLF
            + "Upgrade: WebSocket" + Constants.CRLF
            + "Connection: Upgrade" + Constants.CRLF
            + "Host: localhost" + Constants.CRLF
            + "Origin: http://localhost" + Constants.CRLF
            + Constants.CRLF;

    public WebSocketClient(String address) throws IOException {
        URL url = new URL(address);
        setSelector(SelectorProvider.provider().openSelector());
        new Thread(new Runnable() {
            public void run() {
                select();
            }
        }).start();
        open(url);
    }

    private void open(URL url) throws IOException {
        final SocketChannel socketChannel = SocketChannel.open();
        channel = socketChannel;
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress(url.getHost(), url.getPort()));
        socketChannel.socket().setSoTimeout(30000);
        state = State.CONNECTING;
        getSelector().wakeup();
    }

    @Override
    public void close() throws IOException {
        super.close();
        channel.close();
    }

    private void select() {
        while (state != State.CLOSED) {
            try {
                if (state == State.CONNECTING) {
                    channel.register(getSelector(), SelectionKey.OP_CONNECT);
                }
                getSelector().select();

                Iterator selectedKeys = getSelector().selectedKeys().iterator();
                while (selectedKeys.hasNext()) {
                    SelectionKey key = selectedKeys.next();
                    selectedKeys.remove();
                    process(key);
                }
            } catch (IOException e) {
                logger.log(Level.WARNING, e.getMessage(), e);
            }
            getSelector().wakeup();
        }
    }

    protected void process(SelectionKey key) throws IOException {
        if (key.isValid()) {
            if (key.isConnectable()) {
                disableOp(SelectionKey.OP_CONNECT);
                doConnect();
            } else if (key.isReadable()) {
                doRead();
            }
            enableOp(SelectionKey.OP_READ);
            key.selector().wakeup();
        }
    }

    @Override
    protected void doConnect() throws IOException {
        channel.finishConnect();
        final byte[] bytes = CLIENT_HANDSHAKE.getBytes();
        write(bytes);
        state = State.WAITING_ON_HANDSHAKE;
        super.doConnect();
    }

    @Override
    protected void doRead() throws IOException {
        switch (state) {
            case WAITING_ON_HANDSHAKE:
                final ByteBuffer buffer = ByteBuffer.allocate(WebSocketEngine.INITIAL_BUFFER_SIZE);
                final int read = channel.read(buffer);
                state = State.READY;
                setConnected(true);
                break;
            case READY:
                super.doRead();
                break;
            default:
                break;
        }
    }

    protected void unframe() throws IOException {
        int count;
        do {
            ByteBuffer bytes = ByteBuffer.allocate(WebSocketEngine.INITIAL_BUFFER_SIZE);
            count = channel.read(bytes);
            bytes.flip();
            unframe(bytes);
        } while (count > 0);
    }

    @Override
    protected void write(byte[] bytes) throws IOException {
        final ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
        buffer.put(bytes);
        buffer.flip();
        final int i = channel.write(buffer);
    }

    protected SelectionKey getKey() {
        return channel.keyFor(getSelector());
    }

    void enableOp(final int op) {
        final SelectionKey key = getKey();
        final int ops = key.interestOps();
        final int newOp = ops | op;
        if (newOp != ops) {
            key.interestOps(newOp);
        }
        key.selector().wakeup();
    }

    void disableOp(final int op) {
        final SelectionKey key = getKey();
        final int ops = key.interestOps();
        final int newOp = ops & ~op;
        if (newOp != ops) {
            key.interestOps(newOp);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy