Hatena::ブログ(Diary)

tomoTakaの日記

2013-08-14

WebSocket Echo Client

After having transcribed one of my friends blog about WebSocket, I made client endpoint using Tyrus and Java API for WebSocket on JavaFX.
The Friends Blog is hereJava SEでWebSocketサーバを立てて遊ぶ — 裏紙
And also refer to this Chapter 1. Getting Started

You click the send button to send the message to the server.
Once the message received, client Endpoint adds the message on the ListView.
f:id:tomoTaka:20130813071531p:image:w360

  • Starting server Screen

f:id:tomoTaka:20130812080336p:image:w640

  • code 1

The client Endpoint is constructed with the MessageList which is created in the Echo Client(see code 2)
In the onOpen method, MessageHandler is registered(the received message is added to the MessageList)
The "start connection" message is added to the MessageList when the connection is opened.
Also "close session" message is added to the MessageList when the connection is closed.

public class EchoClienEndpoint extends Endpoint{
    private ObservableList<String> messageList;

    public EchoClienEndpoint(ObservableList<String> messageList) {
        this.messageList = messageList;
    }
    
    @Override
    public void onOpen(Session session, EndpointConfig ec) {
        try {
            session.getBasicRemote().sendText("start connection");
        } catch (IOException ex) {
            Logger.getLogger(EchoClienEndpoint.class.getName()).log(Level.SEVERE, null, ex);
        }
        session.addMessageHandler(new MessageHandler.Whole<String>() {
            @Override
            public void onMessage(String message) {
                messageList.add(0, String.format("received message is %s", message));
            }
        });
    }

    @Override
    public void onClose(Session session, CloseReason closeReason) {
        messageList.add(0, "close session");
    }    
}

When the Open button is clicked, the connection is opened and instantiates the Client Endpoint with messageList(In the openConnection method, see code 1)
ConnectToServer method returns the session so you can use this session to send the message(in the openConnection and addLine2 method)
When the Close button is clicked, the connection is closed(In the closeConnection method)
In addition this code shows how to use the BooleanProperty to disable or enable the open button, the close button, the send button and the message text.

public class EchoClientFX extends Application {
    private Session connectSession;
    private ObservableList<String> messageList = FXCollections.observableArrayList();
    private BooleanProperty connectionProp = new SimpleBooleanProperty(false);

    @Override
    public void start(Stage stage) throws Exception {
        VBox root = new VBox();
        root.setPadding(new Insets(10));
        ListView messageView = new ListView(messageList);
        root.getChildren().addAll(addLine1(), addLine2(), messageView);
        stage.setScene(new Scene(root, 500, 300));
        stage.setTitle("Echo Client");
        stage.show();
    }
    /*
     * add the line1(HBox)
     */
    private Node addLine1(){
        HBox hbox = new HBox();
        hbox.setPadding(new Insets(10));
        hbox.setSpacing(5);
        Button openBtn = new Button("open");
        Button closeBtn = new Button("close");
        openBtn.disableProperty().bind(connectionProp);
        closeBtn.disableProperty().bind(Bindings.not(connectionProp));
        openConnection(openBtn);
        closeConnection(closeBtn);
        hbox.getChildren().addAll(openBtn, closeBtn);
        return hbox;
    }
    /*
     * open the connection to the echo server
     */
    private void openConnection(final Button openBtn) {
        openBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                ClientManager client = ClientManager.createClient();
                ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
                try {
                    URI uri = new URI("ws://localhost:8080/ws/echo");
                    // connect the echo server
                    connectSession = client.connectToServer(new EchoClienEndpoint(messageList), cec, uri);
                } catch (DeploymentException | URISyntaxException | IOException ex) {
                    Logger.getLogger(EchoClientFX.class.getName()).log(Level.SEVERE, null, ex);
                }
                connectionProp.setValue(true);
            }
        });
    }
    /*
     * close the connection
     */
    private void closeConnection(Button closeBtn){
        closeBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                try {
                    connectSession.close();
                    connectionProp.setValue(false);
                } catch (IOException ex) {
                    Logger.getLogger(EchoClientFX.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
    /*
     * add the line2(HBox)
     */
    private Node addLine2(){
        HBox hbox = new HBox();
        hbox.setPadding(new Insets(10));
        hbox.setSpacing(5);
        Label messageLbl = new Label("Message:");
        final TextField messageTxt = new TextField();
        messageTxt.setPrefWidth(200);
        messageTxt.disableProperty().bind(Bindings.not(connectionProp));
        Button sendBtn = new Button("send");
        sendBtn.disableProperty().bind(Bindings.not(connectionProp));
        sendBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                try {
                    // send the message to the echo server
                    connectSession.getBasicRemote().sendText(messageTxt.getText());
                    messageTxt.clear();
                } catch (IOException ex) {
                    Logger.getLogger(EchoClientFX.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        hbox.getChildren().addAll(messageLbl, messageTxt, sendBtn);
        return hbox;
    }
    public static void main(String[] args) {
        launch();
    }
}
  • code 3

The Echo Server which echo the received message back to the client.

@ServerEndpoint("/echo")
public class EchoServerEndpoint {
    @OnOpen
    public void open(Session session){
        System.out.println(String.format("[open]%s", session));
    }
    @OnClose
    public void close(Session session){
        System.out.println(String.format("[close]%s", session));
    }
    @OnMessage
    public String onMessage(String message, Session session){
        System.out.println(String.format("[%s]%s", message, session));
        return message;
    }
}
  • code 4

Run the Echo Server on the hostname "localhost", port "8080" and path "/ws".

public class EchoMain {
    public static void main(String[] args) throws Exception {
        Server server = new Server("localhost", 8080, "/ws", EchoServerEndpoint.class);
        try {
            server.start();
            System.in.read();
        } finally {
            server.stop();
        }
    }
}

The whole code is here.tomoTaka01/WebSocketTest ? GitHub
And You can get the information about Tyrus dependencies hereProject Tyrus - Dependencies
I am not sure that this is the right way to implement the WebSocket client.
Please let me know if you have any advice. Thanks in advance.
I just keep coding....
P.S I amended this app.(see 2013-09-15 - tomoTakaの日記)

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/tomoTaka/20130814/1376434299