V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
2656618087
V2EX  ›  程序员

web在线聊天室该怎么做呢?

  •  
  •   2656618087 · Jul 22, 2013 · 13915 views
    This topic created in 4669 days ago, the information mentioned may be changed or developed.
    本程序员想做个在线聊天室。能放在公网上的。现在不知道用什么实现方式。项目是javaee的 JSP项目。请有相关经验的前辈指点一二!
    现在小程序员有看过DWR,servlet3.0配合前台ajax,发现都能实现,更倾向与servlet3.0的异步服务器推,但是看到有个网站用的这种方式实现,结果聊天室经常出问题。请前辈们帮忙分析分析,该用什么实现呢!最好是支持人数多、性能好的! 小弟先谢过了!
    51 replies    1970-01-01 08:00:00 +08:00
    nybux
        1
    nybux  
       Jul 22, 2013
    我实现的是http长连接推送的,用golang实现的,由于测试程序的性能问题,测试了2万个并发没有问题。
    G2bN4dbX9J3ncp0r
        2
    G2bN4dbX9J3ncp0r  
       Jul 22, 2013
    websocket
    lch21
        3
    lch21  
       Jul 22, 2013
    现在都用QQ, 微信聊天, web聊天室很少人用了吧
    网上也有不少开源的web聊天室程序
    2656618087
        4
    2656618087  
    OP
       Jul 22, 2013
    @nybux 我写了个前台ajax,进入聊天室时通过ajax(startComet一个函数)开始长轮训,目的是请求后台使此用户请求加入到后台用户列表中,此请求就一直挂起,等待有消息推过来 再执行success方法 处理接收到的消息,complete后再发出下一次轮询请求,以此循环。 有个sendmessage函数是负责发送消息的,后台收到此请求,通知列表用户并发送消息至前台。现在主要问题是后台我不知道该怎么写,想用servlet3.0的异步对象AsyncContext 将每个用户的AsyncContext对象缓存起来 就相当于用户列表。但是具体不知道怎么写 怎么入手。能指点下么?给点代码片段 看看可否!谢谢了
    2656618087
        5
    2656618087  
    OP
       Jul 22, 2013
    @lch21 我没找到合适我的!之前看了个开源的auto-comet 但是他不更新 我也没细看!
    2656618087
        6
    2656618087  
    OP
       Jul 22, 2013
    @lidashuang 能讲讲实现思路吗?
    还有个问题就是 我想着这东西不复杂 估计会写的人 一天就搞定了!但是我后台不会写 都琢磨了好久了 没写出来!
    nybux
        7
    nybux  
       Jul 22, 2013
    你的程序里面要存储一张表,就是对应的用户id和asynccontext的表。
    当要给指定用户发消息的时候,就通过用户id把对应的asynccontext对象取出来,返回发送消息。
    我用golang写的。用的是channel阻塞。原理和asyncservlet不太一样。
    2656618087
        8
    2656618087  
    OP
       Jul 22, 2013
    @nybux 我的聊天记录不保存,我之前简单做了个用户id和asynccontext在一个javabean asynUser里保存,然后用一个map存放key为房间id value是一个list里面就放的是此放假所有的asynUser对象,但这样老出问题,并发问题、还有就是发送消息时还没给这个房间的asynccontext发送完,下一条消息已经到达,就导致部分用户接收不到消息。对java的同步、锁什么的不太了解 这块也不到底是不是这样处理的。最烦的就是asynccontext对象 相当于发一次消息 就销毁一次 接着ajax轮询请求,后台再创建个asynccontext对象。麻烦的
    nybux
        9
    nybux  
       Jul 22, 2013
    并发问题是程序逻辑写的不合理,要好好再设计一下。这类程序的开发,我一般都是2线程的,一个线程负责网络收发,一个线程负责业务逻辑。所以在业务这块,我是单线程的,一般来说仅仅是聊天转发,一个cpu core足够处理了,而且也没有锁的问题。
    参考资料:http://www.eecs.harvard.edu/~mdw/proj/seda/
    2656618087
        10
    2656618087  
    OP
       Jul 22, 2013
    @nybux 好的 谢谢 我看看
    Yuansir
        12
    Yuansir  
       Jul 22, 2013
    试试 socket.io
    46fo
        13
    46fo  
       Jul 22, 2013
    @nybux go版发来玩玩啊
    thursday
        14
    thursday  
       Jul 22, 2013
    nodejs socket.io 很简单
    verfino
        15
    verfino  
       Jul 22, 2013
    用浏览器实现 确实推荐下 Node.js的socket.io
    paloalto
        16
    paloalto  
       Jul 22, 2013
    2656618087
        17
    2656618087  
    OP
       Jul 22, 2013
    @thursday 不太会这玩意!入门资料提供吗?
    hoorace
        18
    hoorace  
       Jul 22, 2013
    使用node.js + socket.io比较快就做出来的,网上的demo也比较简单可以帮助你。只是浏览器的兼容问题需要改写一些框架的源码;由于node的内存回收机制不太清楚,outofmemory的情况时有发生。如果业务量不大或者练手,可以考虑。
    目测小米的客服也是node.js开发的!
    我参与了okhqb.com的右侧的联系客服,是node.js+socket.io+redis开发的!
    verfino
        19
    verfino  
       Jul 22, 2013
    @hoorace Node.js 的 socket.io 貌似对浏览器近乎是全兼容的....(ie6,7,8 chrome firefox safari)
    hoorace
        20
    hoorace  
       Jul 22, 2013
    @verfino 用了你就知道了,某些浏览器的一些细节,需要你修改socket.io的源码。我至少修改过3处。
    wudikua
        21
    wudikua  
       Jul 22, 2013
    redis pub/sub 都写好了现成的推送,自己写个长连接服务器,配合前端long polling接受数据,ajax get发送数据就行了。
    fansgentle
        22
    fansgentle  
       Jul 22, 2013
    @thursday +1 我的快要上线了,占位~~
    wity_lv
        23
    wity_lv  
       Jul 23, 2013
    @verfino
    @hoorace
    @paloalto
    试试我这个:
    https://github.com/lvjian700/node-pusher
    基于socket.io,项目很简单,仅用来做数据推送:
    web, java, ios 客户端都有。

    Web端:
    $(function() {
    var url = 'http://localhost:3000/';
    var room = '/column';

    var pusher = new Pusher(url);

    pusher.sub(room, function(data) {
    console.log('subscribe /column room success.');
    console.log(data);
    });

    pusher.on('news', function(data) {
    console.log('receive data from xx room.');
    console.log(data);
    });

    $('#btnSent').click(function() {
    var text = $('#message').val();
    pusher.pub(room, 'news', {sender: 'lvjian', msg: text});

    $('#message').val('');
    });
    });

    Java端:
    public class Sample {

    static String to = "/column";
    static String event = "news";

    public static void main(String[] args) throws MalformedURLException, JSONException {

    Pusher pusher = new Pusher("http://127.0.0.1:3000/");

    // This line is cached until the connection is establisched.
    for(int i = 0; i < 10; i++) {
    JSONObject json = new JSONObject();
    json.put("msg", "haha");

    pusher.pub(to, event, json.toString());

    try {
    Thread.sleep(500);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }

    }

    System.exit(0);
    }

    }

    iOS(尚未整理,直接用的Socket.IO for Cocoas)
    _socketIO = [[SocketIO alloc] initWithDelegate:self];
    NSString *host = [RKObjectManager sharedManager].baseURL.host;
    [_socketIO connectToHost:host onPort:3000];
    [_socketIO sendEvent:@"sub" withData:@{@"topic" : @"/changji"}];
    //...
    - (void) socketIO:(SocketIO *)socket didReceiveEvent:(SocketIOPacket *)packet {
    //这里接收事件
    }



    @nybux 求测试方案,我想对node-pusher服务做个性能测试。
    nybux
        24
    nybux  
       Jul 23, 2013   ❤️ 1
    我的测试程序是用nodejs写的,不过感觉性能不是很好

    #!/usr/bin/node
    var net = require('net');
    var count = 0;
    var maxUser = 5000;

    function sendRequest(client, i) {
    client.write('GET /poll?uid=-' + i.toString() + ' HTTP/1.1\r\nCookie: ASP.NET_SessionId=' + i.toString() + '\r\n\r\n')
    }

    function poll(uid) {
    var client = new net.Socket();
    client.connect(8080, '127.0.0.1', function() {
    setTimeout(function(){
    sendRequest(client, uid);
    }, Math.random() * 3000);
    });
    client.on('data', function(data) {
    count++;
    msg = data.toString().split('\r\n\r\n')[1];
    if (msg != "") {
    //console.log('recv,' + uid + ':{' + msg + '}');
    }
    setTimeout(function(){
    sendRequest(client, uid);
    }, Math.random() * 3000);
    });
    client.on('close', function() {
    console.log(uid.toString() + ':close!!!!');
    client = new net.Socket();
    poll(uid);
    })
    }

    setInterval(function() {
    console.log('msg count:' + count);
    }, 5000);

    for (i = 1000; i < 1000 + maxUser; ++i) {
    poll(i)
    }
    2656618087
        25
    2656618087  
    OP
       Jul 23, 2013
    @fansgentle 你是怎么做的呢
    andyhu
        26
    andyhu  
       Jul 23, 2013
    @hoorace 修改的都是哪里?建议创建个pull request贡献回去吧
    fansgentle
        27
    fansgentle  
       Jul 23, 2013
    @2656618087 NodeJS、Socket.io、ExpressJS、Bootstrap、NoSQL ...
    yushuiyouyue
        28
    yushuiyouyue  
       Jul 24, 2013
    我做了一个是用java+redis来完成的。
    redis里面来存放user和用户的消息。客户端使用ajax向服务器发送消息和获取消息
    timepast
        29
    timepast  
       Jul 24, 2013
    PushLets
    rainchen
        30
    rainchen  
       Jul 24, 2013
    5分钟在线开发一个聊天室
    https://www.firebase.com/tutorial/
    wity_lv
        31
    wity_lv  
       Jul 24, 2013
    @timepast pushlet 还是别推荐了, 上手难度不小。
    2656618087
        32
    2656618087  
    OP
       Jul 25, 2013
    @yushuiyouyue 前台ajax到时好写 ,后台 不怎么会写,求点学习代码。可否发到[email protected]邮箱,十分感谢
    2656618087
        33
    2656618087  
    OP
       Jul 25, 2013
    @rainchen 这是什么情况?
    2656618087
        34
    2656618087  
    OP
       Jul 25, 2013
    @yushuiyouyue 给点代码!后台的,十分感谢 我后台也是java的
    2656618087
        35
    2656618087  
    OP
       Jul 25, 2013
    @yushuiyouyue 给点代码!后台的,十分感谢 我后台也是java的。谢谢了!
    az402
        36
    az402  
       Jul 25, 2013
    CometD
    erylee
        37
    erylee  
       Jul 25, 2013
    直接用哥的:

    webim20.cn

    前台代码:

    github.com/webim
    2656618087
        38
    2656618087  
    OP
       Jul 29, 2013
    这几天看了看,还是决定用servlet3.0的异步。计划是这样,每个人进入聊天室房间,调用一个servlet,都把这个异步对象AsyncContext存入一个map里,key为房间id,value为存放AsyncContext的list,发送消息调用messageServlet 将收到的消息存入一个list内,message model有房间ID用于区别该消息是那个房间那个人发的。后台再写个timer定时器,每1秒检查message list里是否有新消息,如果有就调用该房间的所有异步AsyncContext对象 散播消息。我理解这个就是一次轮询完成。客户端收到消息,然后再重复上面的过程建立一次新的轮询。不知道这样做的话可行吗?timer 一秒检查一次 会对服务器 有压力吗?求指导
    @erylee @az402 @yushuiyouyue @rainchen @timepast @yushuiyouyue @nybux @wity_lv @paloalto @thursday @xdeng @lidashuang @lch21
    thursday
        39
    thursday  
       Jul 29, 2013
    socket.io 天生就好像是为了 聊天室而生。。 楼主 为何不试试看
    davepkxxx
        40
    davepkxxx  
       Jul 29, 2013
    dwr是通 过长连接+定时断开重连 来实现的,如果你不想手动做这个事情,那么用dwr是最好的选择了,或者你也可以选择flash(不少移动浏览器不支持)、html5(ie6~8不支持)、awt(需要客户安装jar)来实现。
    isayme
        41
    isayme  
       Jul 29, 2013
    tlk.io好像是nodejs+socket.io做的,目测很不错
    wity_lv
        42
    wity_lv  
       Jul 29, 2013
    @2656618087 我想说,你在重造轮子。node.js 的 socket.io 模块已经把Pub/Sub这个事情处理的很好。
    如果你专注于技术学习,可以用servlet 3.0试试。 第一步需要使用底层api实现一个pub/sub模型,之后再基于这层进行聊天室的开发。
    2656618087
        43
    2656618087  
    OP
       Jul 29, 2013
    这么说大概明白了。谢谢你 @wity_lv @isayme @davepkxxx @thursday
    照你说我那样做除了麻烦费事,其实也是可行的对不?我这个试完了 研究研究 socket.io 和 dwr 再次感谢。
    wity_lv
        44
    wity_lv  
       Jul 29, 2013
    @2656618087 折腾吧,当时我也折腾过,后来选择了pushlet, 现在用socket.io.
    Actrace
        45
    Actrace  
       Jul 29, 2013
    最近折腾了一个Ajax Online Chat Demo,楼主可以看看.
    http://try.maxfs.org
    几乎实时.
    Actrace
        46
    Actrace  
       Jul 29, 2013
    地址错了,补充一下.
    http://try.maxfs.org/chat.php
    xdyl
        47
    xdyl  
       Jul 30, 2013
    http://www.ptteng.com

    WebSocket实现的.
    gracechen
        48
    gracechen  
       Aug 3, 2013
    楼主有兴趣我们邮件联系?[email protected]
    gracechen
        49
    gracechen  
       Aug 3, 2013
    忘记问。。楼主和@nybux 在帝都吗?
    nybux
        50
    nybux  
       Aug 4, 2013
    @gracechen 魔都
    gagahjt
        51
    gagahjt  
       Aug 6, 2013
    nodejs+socket.io 做压力测试有什么好的方法和工具么?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2507 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 90ms · UTC 06:48 · PVG 14:48 · LAX 23:48 · JFK 02:48
    ♥ Do have faith in what you're doing.