【Lolttery】项目开发日志 (七)socket io 结合 react js实现简单聊天室

因为项目中需要用到实时网页聊天,于是了解到socket.io框架

##1 概述 socket.io封装了websocket等通讯方式,可以实现服务器与浏览器之间的信息推送的功能。

官方网站 提供了一个非常简单的聊天室demo,然而是基于nodejs来做的。为了统一一下,专门去找了一个基于java的socket.io服务端NettySocketIO.

socket.io的原理是基于事件的推送。对于数据的处理就是一个个的事件触发。

比如服务器的某个数据更新了,需要所有浏览器同步更新,就向所有浏览器发送一个更新事件,内容就是更新的数据,或者数据较多的时候告诉客户端自己来取。

这种模型在很多异步服务器中都有使用,在java中,Netty就是一个很典型的事件驱动服务器。于是用netty来做socketio也很顺理成章的样子。至于官方给出的node.js也是以事件驱动而闻名。

##2 服务端

单纯的一个socketio服务器启动起来十分简单:

public void start(){
        Configuration configuration = new Configuration();
        configuration.setHostname("0.0.0.0");
        configuration.setPort(9223);
        socketioServer = new SocketIOServer(configuration);
        //为指定的事件添加监听
        socketioServer.addEventListener("sendMessage", SimpleChatEvent.class ,
                new SimpleChatListener(socketioServer));
        logger.info("Socket.io 服务已经启动");
        socketioServer.start();
    }
复制代码

代码看上去很明了。新建一个配置,用配置创建一个服务,添加事件监听并启动。

在NettySocketIO中,事件需要指明一个名称,在这里是"sendMessage",后面是一个java bean,指明了这个事件需要附带的参数。

实现聊天室的关键就在于SimpleChatListener这个类中:

/**
 * 简单广播的聊天服务器
 * Created by shizhida on 16/5/7.
 */
public class SimpleChatListener implements DataListener<SimpleChatEvent> {

    SocketIOServer server;

    UserService userService = DubboClient.getClient(UserService.class);

    Logger logger = LoggerFactory.getLogger(SimpleChatListener.class);

    public SimpleChatListener(SocketIOServer server){
        this.server = server;
    }

    @Override
    public void onData(SocketIOClient client, SimpleChatEvent data, AckRequest ackSender) throws Exception {
        // broadcast messages to all clients

        logger.info("recive message:"+data.getMessage());
        String ticket = data.getTicket();
        //去其它的服务中获取用户信息
        XOResponse response = userService.getMyInfo(ticket);
        if(response.getResultStatus() != CommonKeys.response_status_success){
            return;
        }
        Map<String,Object> user = (Map<String, Object>) response.getBody("user");

        //拼装返回的参数
        Message message = new Message();
        message.setMessage(data.getMessage());
        message.setTime(new SimpleDateFormat("hh:mm:ss").format(new Date()));
        message.setUserIcon((String) user.get("icon"));
        message.setUserName((String) user.get("username"));

        server.getBroadcastOperations().sendEvent("newMessage", message);
        logger.info("send message to client, userName:"+message.getUserName());
    }
}
复制代码

在此类中实现DataListener接口,可以见到在onData方法中,收到的data类型就是我们前面指定的SimpleChatEvent。

收到消息后,根据用户的ticket获取用户信息,并组装出返回的消息,通过广播发送到所有的客户端,就会在所有的浏览器都收到这条消息。

在这个demo中,并没有添加诸如聊天记录处理,以及更多其它的花式事件等功能,但是看过代码后就会发现这些功能只是简单的扩展。

##3 浏览器

因为在项目中使用了react,还需要在react中集成socketio的功能。

为了方便调用,我将socketio的实例扔在了组件的state中:

getInitialState: function() {
        var ticket = $.cookie("ticket");
        var socket =  io.connect('http://server.interestpal.com:9223');
        socket.on('newMessage', this.reciveMessage);
        return {
            messages: [],
            socket: socket,
            ticket: ticket,
            content: ""
        };
    },

复制代码

reciveMessage是此组件中的一个方法。用来在接收到消息时更新state中的messages数组 组件中同样提供一个send方法,用于向服务器发送消息:

	reciveMessage : function(data){

        var msgs = this.state.messages;
        msgs.push(data);
        this.setState({
            messages:msgs
        });

    },
    send : function(){
        if(!$.cookie("ticket")){
            alert("用户尚未登录,请登陆后操作")
        }
        if(this.state.content=="")
            return;
        this.state.socket.emit("sendMessage",{
            ticket:$.cookie("ticket"),
            message:this.state.content
        });
        this.setState({
            content:""
        });
    }
复制代码

剩下的事情就是要根据数据来铺页面了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值