官术网_书友最值得收藏!

Building a signaling server in Java

In this recipe, we will cover the implementation of a signaling server in Java.

Getting ready

This recipe uses Java, so you should have Java Developer Kit (JDK) installed on your machine. You can download the appropriate version of JDK for your platform from its web page at http://www.java.com.

Java 7 has its own API to implement a WebSocket application. Previous versions of Java don't have the native support of WebSockets. In this recipe, we will cover the universal solution that works in different Java versions and is based on the third-party component, which you can find on its home page at http://java-websocket.org. This project is also present on GitHub at https://github.com/TooTallNate/Java-WebSocket.

You need to download and install the Java-WebSocket library; it should then be linked to your project.

In this recipe, we pack signaling messages into the JSON format before sending, so we need a Java library to work with JSON structures. For this purpose, we will use Java classes from JSON's home page, http://www.json.org/java/.

Download these classes and link them to your project, or you can just put these classes into your project's folder structure and compile it all together.

It is assumed that you have experience of programming in Java, so we will not cover the basic questions like how to start a Java application and so on.

How to do it…

Create a new project in your Java IDE and link the JSON libraries along with the Java-WebSocket library.

The following code represents a simple signaling server. Compile it and start a Java console application as usual:

package com.webrtcexample.signaler;

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import org.json.JSONException;
import org.json.JSONObject;

import java.net.InetSocketAddress;
import java.util.*;

public class Main extends WebSocketServer {

    private static Map<Integer,Set<WebSocket>> Rooms = new HashMap<>();
    private int myroom;

    public Main() {
        super(new InetSocketAddress(30001));
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
        System.out.println("New client connected: " + conn.getRemoteSocketAddress() + " hash " + conn.getRemoteSocketAddress().hashCode());
    }

    @Override
    public void onMessage(WebSocket conn, String message) {

        Set<WebSocket> s;
        try {
            JSONObject obj = new JSONObject(message);
            String msgtype = obj.getString("type");
            switch (msgtype) {
                case "GETROOM":
                    myroom = generateRoomNumber();
                    s = new HashSet<>();
                    s.add(conn);
                    Rooms.put(myroom, s);
                    System.out.println("Generated new room: " + myroom);
                    conn.send("{\"type\":\"GETROOM\",\"value\":" + myroom + "}");
                    break;
                case "ENTERROOM":
                    myroom = obj.getInt("value");
                    System.out.println("New client entered room " + myroom);
                    s = Rooms.get(myroom);
                    s.add(conn);
                    Rooms.put(myroom, s);
                    break;
                default:
                    sendToAll(conn, message);
                    break;
            }
        } catch (JSONException e) {
            sendToAll(conn, message);
        }
        System.out.println();
    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
        System.out.println("Client disconnected: " + reason);
    }

    @Override
    public void onError(WebSocket conn, Exception exc) {
        System.out.println("Error happened: " + exc);
    }

    private int generateRoomNumber() {
        return new Random(System.currentTimeMillis()).nextInt();
    }

    private void sendToAll(WebSocket conn, String message) {
        Iterator it = Rooms.get(myroom).iterator();
        while (it.hasNext()) {
            WebSocket c = (WebSocket)it.next();
            if (c != conn) c.send(message);
        }
    }

    public static void main(String[] args) {
        Main server = new Main();
        server.start();
    }
}

Once the application starts, it will listen on the TCP port 30001 for WebSocket messages from clients. You can write simple client applications to test the signaling server—refer to the Making and answering calls recipe.

Note that you can find a Maven-based project for this example supplied with this book.

How it works…

First of all, the client sends a GETROOM message to the signaling server that is listening on TCP port 30001. The server generates a new virtual room number, stores it, and sends it back to the client.

The client constructs a new access URL using the virtual room number received from the server. Then, the second client uses this URL to enter the virtual room and establish a call to the first client.

The second client sends the room number it got from the URL to the signaling server. The server associates the client with the virtual room number. Then, the client makes a call, using signaling server, which forwards its messages to the first client that is present in the room already. The first client answers the call, also using the signaling server as the middle point.

So both clients exchange the necessary data (including network details) and then establish direct peer-to-peer connection. After the connection is established, peers don't use the server anymore.

There's more…

The WebSocket signaling server in Java can be implemented using a Java EE stack. For more details, take a look at the home page of JSR 356 at http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html.

You can also find an example at https://github.com/hsilomedus/web-sockets-samples/tree/master/eesockets.

Another solution is to use Spring 4. It has WebSocket support out of the box. For details on this solution, take a look at the example on GitHub at https://github.com/hsilomedus/web-sockets-samples/tree/master/springsockets.

See also

  • For an alternative solution, you can refer to the Building a signaling server in Erlang recipe
主站蜘蛛池模板: 汉源县| 东方市| 平江县| 钦州市| 同江市| 曲阜市| 尼勒克县| 博爱县| 色达县| 锡林浩特市| 遵义县| 临夏市| 河曲县| 晋州市| 舒兰市| 札达县| 南岸区| 郑州市| 建平县| 河曲县| 安西县| 临湘市| 林西县| 同心县| 剑川县| 新野县| 内丘县| 广昌县| 清流县| 日土县| 治县。| 土默特左旗| 乌兰察布市| 剑阁县| 永顺县| 玛多县| 离岛区| 衡阳县| 铅山县| 黑龙江省| 光泽县|