java socketio 入门教程(自制聊天系统)

java socketio 入门Demo

WebSocket :一种通信协议 ,其作用建立一个连接通道,使数据交互从传统的请求响应的方式 改为了实时的双向推送 ,解决了 http 协议的部分不足

这里就直接整合了spring boot,spring boot 太香了

聊天demo代码(服务器版)

  1. 依赖(没贴spring boot的)
		<dependency>
			<groupId>com.corundumstudio.socketio</groupId>
			<artifactId>netty-socketio</artifactId>
			<version>1.7.11</version>
		</dependency>
  1. 设置全局的配置对象
		@Configuration
public class SocketConfig {

    private int PORT = 8081;

    private String HOST = "localhost";


    @Bean
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        //不设置主机、默认绑定0.0.0.0 or ::0
//        config.setHostname(WSS_HOST);
        config.setPort(PORT);
        //这里还可以认证很多设置 比如仓库什么的
        //身份验证
        config.setAuthorizationListener(handshakeData -> {
            //这里没有启用任何认证 直接返回为 true,可以在这里写用户认证的逻辑

            //http://localhost:8081?username=test&password=test
            //            //例如果使用上面的链接进行connect,可以使用如下代码获取用户密码信息
            //            //String username = data.getSingleUrlParam("username");
            //            //String password = data.getSingleUrlParam("password");

            return true;
        });
        final SocketIOServer server = new SocketIOServer(config);
        return server;
    }

    @Bean
    public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
        return new SpringAnnotationScanner(socketServer);
    }
}
  1. 编写消息处理者

@Component
public class MessageHandler {
    private static final Logger log = LoggerFactory.getLogger(MessageHandler.class);
    //会话集合,用来存储所有的客户端信息
    private static final ConcurrentSkipListMap<String, ClientInfo> webSocketMap = new ConcurrentSkipListMap<>();
    //静态变量,用来记录当前在线连接数。(原子类、线程安全)
    private static AtomicInteger onlineCount = new AtomicInteger(0);
	//服务器全局对象 发送信息 就靠它了
    private final SocketIOServer server;

    @Autowired
    public MessageHandler(SocketIOServer server) {
        this.server = server;
    }

    /**
     * connect事件处理,当客户端发起连接时将调用,每次建立连接都会调用一次该方法
     *
     * @param client
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {
        // clientid 来自请求地址中
        String clientId = client.getHandshakeData().getSingleUrlParam("clientid");
        log.info("web socket连接:" + clientId);
        UUID session = client.getSessionId();
        ClientInfo si = webSocketMap.get(clientId);
        // 如果没有连接信息、则新建会话信息
        if (si == null) {
            si = new ClientInfo();
            si.setOnline(true);

            //在线数加1
            log.info("socket 建立新连接、sessionId:" + session + "、clientId:" + clientId + "、当前连接数:" + onlineCount.incrementAndGet());
        }
        // 更新客户端连接信息
        si.setLeastSignificantBits(session.getLeastSignificantBits());
        si.setMostSignificantBits(session.getMostSignificantBits());
        si.setLastConnectedTime(new Date());
        //将会话信息更新保存至集合中
        webSocketMap.put(clientId, si);


    }


    public void sendMessage(Object Message) {
        // 这个方法 会向所有的客户端 发送信息。 事件名为 message_event
        // 只有客户端有监听这个事件 就能接收到信息
        for (String clientId : webSocketMap.keySet()) {
            ClientInfo clientInfo = webSocketMap.get(clientId);
            System.out.printf("开始往客户端%s发送数据", clientId);
            UUID session = new UUID(clientInfo.getMostSignificantBits(), clientInfo.getLeastSignificantBits());
            server.getClient(session).sendEvent("message_event", Message);
        }
    }

    /**
     * 断开连接
     *
     * @param client
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        String clientId = client.getHandshakeData().getSingleUrlParam("clientid");
        webSocketMap.remove(clientId);
        //在线数减1
        log.info("socket 断开连接、sessionId:" + client.getSessionId() + "、clientId:" + clientId + "、当前连接数:" + onlineCount.decrementAndGet());
    }

    /**
     * 消息接收入口,当接收到消息后,查找发送目标客户端,并且向该客户端发送消息,且给自己发送消息
     *
     * @param client
     * @param request
     * @param data
     */

    // onEvnt 对某个事件进行监听 当客户端有触发这个事件时候 调用。这里是一个聊天的逻辑处理
    @OnEvent(value = "message_event")
    public void onEvent(SocketIOClient client, AckRequest request, MessageInfo data) {
        // MessageInfo 该对象 由客户端发送事件时候提供
        String targetClientId = data.getTargetClientId();
        ClientInfo clientInfo = webSocketMap.get(targetClientId);

        //如果目标在线 那么发送消息,如果不在线 就不进行处理
        if (clientInfo != null && clientInfo.isOnline()) {
            UUID target = new UUID(clientInfo.getMostSignificantBits(), clientInfo.getLeastSignificantBits());
            log.info("目标会话UUID:" + target);
            MessageInfo sendData = new MessageInfo();
            sendData.setSourceClientId(data.getSourceClientId());
            sendData.setTargetClientId(data.getTargetClientId());
            sendData.setMsg(data.getMsg());
            // 向当前会话发送信息
            client.sendEvent("message_event", sendData);
            // 向目标会话发送信息
            server.getClient(target).sendEvent("message_event", sendData);
        }
    }

    /**
     * socket会话信息
     * 下面是自定义的一些消息对象
     */

    @Data
    public class ClientInfo {
        private String clientId;
        private boolean isOnline;
        private long mostSignificantBits;
        private long leastSignificantBits;
        private Date lastConnectedTime;

    }

    /**
     * 消息对象
     */
    public static class MessageInfo {
        //源客户端id
        private String sourceClientId;
        //目标客户端id
        private String targetClientId;
        //消息内容
        private String msg;
        // get/set方法 ....


        public void setSourceClientId(String sourceClientId) {
            this.sourceClientId = sourceClientId;
        }

        public void setTargetClientId(String targetClientId) {
            this.targetClientId = targetClientId;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public String getSourceClientId() {
            return sourceClientId;
        }

        public String getTargetClientId() {
            return targetClientId;
        }

        public String getMsg() {
            return msg;
        }
    }
}

客户端代码

客户端1

<!DOCTYPE html>
<html>
<head lang="zh">
    <meta charset="utf-8"/>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>Demo Chat</title>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
    <!--moment js下载地址:http://momentjs.com/ -->
    <script src="moment.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></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>
    <script>
        var clientId = 'user1',targetId = 'user2';
        var socket = io.connect('http://localhost:8081?clientid=' + clientId);
        socket.on('connect', function () {
            showMsg('<span class="connect-msg">成功连接到服务器!</span>');
        });

        socket.on('message_event', function (data) {
            showMsg('<br /><span class="username-msg">' + new Date().getHours()+' '+new Date().getMinutes()+' '+new Date().getSeconds()+ '</span> ' + data);
        });
        socket.on('disconnect', function () {
            showMsg('<span class="disconnect-msg">服务已断开!</span>');
        });
        function sendDisconnect() {
            socket.disconnect();
        }
        function sendMessage() {
            var message = $('#msg').val();
            $('#msg').val('');
            var jsonObject = {
                sourceClientId: clientId,
                targetClientId: targetId,
                msg: message
            };
            socket.emit('message_event', jsonObject);
        }
        function showMsg(message) {
            // alert(message)
            // var currentTime = "<span class='time'>" + moment().startOf('hour').fromNow() + "</span>";
            // var element = $("<div>" + currentTime + "" + message + "</div>");
            $('#console').append(message);
        }
        $(document).keydown(function (e) {
            if (e.keyCode == 13) {
                $('#send').click();
            }
        });
    </script>
</head>
<body>
<h1>Netty-socket.io Demo</h1><br/>
<div id="console" class="well"></div>
<form class="well form-inline" onsubmit="return false;">
    <input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>&nbsp;&nbsp;
    <button type="button" onClick="sendMessage()" class="btn" id="send">Send</button>&nbsp;&nbsp;
    <button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
</html>

客户端2

<!DOCTYPE html>
<html>
<head lang="zh">
    <meta charset="utf-8"/>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>Demo Chat</title>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
    <!--moment js下载地址:http://momentjs.com/ -->
    <script src="moment.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></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>
    <script>
        var clientId = 'user2',targetId = 'user1';
        var socket = io.connect('http://localhost:8081?clientid=' + clientId);
        socket.on('connect', function () {
            showMsg('<span class="connect-msg">成功连接到服务器!</span>');
        });

        socket.on('message_event', function (data) {
            showMsg('<br /><span class="username-msg">' + new Date().getHours()+' '+new Date().getMinutes()+' '+new Date().getSeconds()+ '</span> ' + data);
        });
        socket.on('disconnect', function () {
            showMsg('<span class="disconnect-msg">服务已断开!</span>');
        });
        function sendDisconnect() {
            socket.disconnect();
        }
        function sendMessage() {
            var message = $('#msg').val();
            $('#msg').val('');
            var jsonObject = {
                sourceClientId: clientId,
                targetClientId: targetId,
                msg: message
            };
            socket.emit('message_event', jsonObject);
        }
        function showMsg(message) {
            // alert(message)
            // var currentTime = "<span class='time'>" + moment().startOf('hour').fromNow() + "</span>";
            // var element = $("<div>" + currentTime + "" + message + "</div>");
            $('#console').append(message);
        }
        $(document).keydown(function (e) {
            if (e.keyCode == 13) {
                $('#send').click();
            }
        });
    </script>
</head>
<body>
<h1>Netty-socket.io Demo</h1><br/>
<div id="console" class="well"></div>
<form class="well form-inline" onsubmit="return false;">
    <input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>&nbsp;&nbsp;
    <button type="button" onClick="sendMessage()" class="btn" id="send">Send</button>&nbsp;&nbsp;
    <button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
</html>

同时启动这个两个就能进行聊天了

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
完整全套资源下载地址:https://download.csdn.net/download/qq_27595745/70898746 【完整课程列表】 完整版 Java基础入门教程 Java程序语言设计 01 java语言基础 Java语言概述(共24页).ppt 完整版 Java基础入门教程 Java程序语言设计 02 java语法基础 Java语法基础(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 02 java语法基础 Java语法基础2(共24页).ppt 完整版 Java基础入门教程 Java程序语言设计 03 java对象 集合框架(共18页).ppt 完整版 Java基础入门教程 Java程序语言设计 03 java对象 类和对象1(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 03 java对象 类与对象2(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 03 java对象 类与对象3(共24页).ppt 完整版 Java基础入门教程 Java程序语言设计 03 java对象 类与对象4(共35页).ppt 完整版 Java基础入门教程 Java程序语言设计 04 IO流 输入输出流(共31页).ppt 完整版 Java基础入门教程 Java程序语言设计 05 GUI AWT 事件模型(共27页).ppt 完整版 Java基础入门教程 Java程序语言设计 05 GUI GUI 编程(共37页).ppt 完整版 Java基础入门教程 Java程序语言设计 05 GUI Swing(共41页).ppt 完整版 Java基础入门教程 Java程序语言设计 06 异常处理 异常和垃圾收集(共27页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 JDBC(共21页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 线程(共23页).ppt

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值