Web push service based on netty socket IO

Time:2021-7-30

In web projects, it is a common business requirement for servers to push messages to web pages. The push technology of PC can be realized by establishing a long connection with socket. In traditional web services, the client sends a request and the server gives a response. But now the intuitive requirement is to allow the server to actively push messages to the client when there is no request from the client within a specific time. In the recent early warning system, the service side needs to push the commodity market and K-line related data to the early warning system, so the commonly used web side push methods are investigated. Common methods mainly include the following:

  • Polling: Ajax sends requests to the server every once in a while to ask if the data has changed, so as to make incremental updates. The polling interval becomes a problem: if the interval is too short, a large number of requests will be sent to the server, which will affect the server load; The interval is too long, and the real-time performance of business data cannot be guaranteed. Company. The advantage of using polling is that the implementation logic is simple, but the disadvantage is that there are a large number of invalid requests, and the server load is high when the number of users is large. Therefore, polling is usually used when the number of concurrent messages is small and the real-time requirements of messages are not high.
  • Long polling Technology: the client sends an Ajax request to the server. After receiving the request, the server holds the connection and returns the response information and closes the connection until there is a new message or timeout (setting). After the client processes the response information, it sends a new request to the server. Long polling technology has the advantages of high real-time message and no frequent requests without messages; The disadvantage is that maintaining the connection between the server and the client will consume some resources.
  • Plug ins provide socket methods: for example, flash, XMLSocket, Java applet socket interface and socket wrapped in ActiveX. The advantage is that it supports native sockets, which is similar to the implementation of PC and mobile terminals; The disadvantage is that the browser needs to install the corresponding plug-ins.
  • WebSocket: is a network technology for full duplex communication between browser and server provided by HTML5. Its advantage is to better save server resources and bandwidth and achieve real-time communication; The disadvantage is that it is not popular at present, and the browser support is not good;

    To sum up, considering browser compatibility and performance, long polling is a better way. Netty socketio is an open source socket.io server-side java implementation, which is based on the netty framework. The project address is:https://github.com/mrniko/net…

The following is a simple chat room function based on netty socketio. Firstly, dependency is introduced:

<dependency>
 <groupId>com.corundumstudio.socketio</groupId>
 <artifactId>netty-socketio</artifactId>
 <version>1.7.3</version>
</dependency>

Define listen, and the user listens to onconnect, disconnect and onmsg events:

@Service("eventListenner")
public class EventListenner {
    @Resource(name = "clientCache")
    private SocketIOClientCache clientCache;
 
    @Resource(name = "socketIOResponse")
    private SocketIOResponse socketIOResponse;
     
    @OnConnect
    public void onConnect(SocketIOClient client) {
       System.out.println ("establish connection");
    }
 
    @OnEvent("OnMSG")
    public void onSync(SocketIOClient client, MsgBean bean) {
        System. Out. Printf ("received message - from:% s to:% s \ n", bean. Getfrom(), bean. Getto());
        clientCache.addClient(client, bean);
        SocketIOClient ioClients = clientCache.getClient(bean.getTo());
        System.out.println("clientCache");
        if (ioClients == null) {
            System. Out. Println ("the user you sent the message is not online");
            return;
        }
        socketIOResponse.sendEvent(ioClients,bean);
    }
 
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        System.out.println ("close connection");
    }
}

Define message sending class:

@Service("socketIOResponse")
public class SocketIOResponse {
    public void sendEvent(SocketIOClient client, MsgBean bean) {
        System. Out. Println ("push message");
        client.sendEvent("OnMSG", bean);
    }
}

To define and save all web connections:

@Service("clientCache")
public class SocketIOClientCache {
    //String: eventtype
    private Map<String,SocketIOClient> clients=new ConcurrentHashMap<String,SocketIOClient>();
 
    //Users send messages to add
    public void addClient(SocketIOClient client,MsgBean msgBean){
        clients.put(msgBean.getFrom(),client);
    }
 
    //Remove on user exit
    public void remove(MsgBean msgBean) {
        clients.remove(msgBean.getFrom());
    }
     
    //Get all
    public  SocketIOClient getClient(String to) {
        return clients.get(to);
    }
}

Define server:

//Inherit initializingbean to make spring load the configuration file and automatically run the following methods
@Service("chatServer")
public class ChatServer implements InitializingBean{
    @Resource
    private EventListenner eventListenner;
    public void afterPropertiesSet() throws Exception {
        Configuration config = new Configuration();
        config.setPort(9098);
         
        SocketConfig socketConfig = new SocketConfig();
        socketConfig.setReuseAddress(true);
        socketConfig.setTcpNoDelay(true);
        socketConfig.setSoLinger(0);
        config.setSocketConfig(socketConfig);
        config.setHostname("localhost");
         
        SocketIOServer server = new SocketIOServer(config);
        server.addListeners(eventListenner);
        server.start();
        System.out.println ("start normally");
    }
}

Define msgbean:

public class MsgBean { 
    private String from;
    private String to;
    private String content;
     
    public String getFrom() {
        return from;
    }
    public void setFrom(String from) {
        this.from = from;
    }
    public String getTo() {
        return to;
    }
    public void setTo(String to) {
        this.to = to;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
     
    @Override
    public String toString() {
        return "MsgBean [from=" + from + ", to=" + to + ", content=" + content + "]";
    }
}

Define main:

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/applicationContext-push.xml");
        context.start();
        context.getBean("chatServer");
    }
}

HTML page:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Socketio chat</title>
<script type="text/javascript"></script>
<script type="text/javascript"></script>
<style>
body {
    padding: 20px;
}
#console {
    height: 400px;
    overflow: auto;
}
.username-msg {
    color: orange;
}
.connect-msg {
    color: green;
}
.disconnect-msg {
    color: red;
}
.send-msg {
    color: #888
}
</style>
</head>
<body>
    <h1>Netty-socketio chat demo</h1>
    <br />
    <div id="console" class="well"></div>
    <form class="well form-inline" onsubmit="return false;">
        <input id="from" class="input-xlarge" type="text" placeholder="from. . . " />
        <input id="to" class="input-xlarge" type="text" placeholder="to. . . " />
        <input id="content" class="input-xlarge" type="text" placeholder="content. . . " />
        <button type="button" onClick="sendMessage()" class="btn">Send</button>
        <button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
    </form>
</body>
<script type="text/javascript">
    var socket = io.connect('http://localhost:9098');
    socket.on('connect',function() {
        output('<span class="connect-msg">Client has connected to the server!</span>');
    });
     
    socket.on('OnMSG', function(data) {
        output('<span class="username-msg">' + data.content + ' : </span>');
    });
     
    socket.on('disconnect',function() {
        output('<span class="disconnect-msg">The client has disconnected! </span>');
    });
     
    function sendDisconnect() {
        socket.disconnect();
    }
     
    function sendMessage() {
        var from = $("#from").val();
        var to = $("#to").val();
        var content = $('#content').val();
        socket.emit('OnMSG', {
            from : from,
            to : to,
            content : content
        });
    }
     
    function output(message) {
        var currentTime = "<span class='time' >" + new Date() + "</span>";
        var element = $("<div>" + currentTime + " " + message + "</div>");
        $('#console').prepend(element);
    }
</script>
</html>

Related articles:
Web push service based on netty socket IO
Gitee source code socket.io and netty socketio