web在线聊天室该怎么做呢? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
2656618087
V2EX    程序员

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

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

    webim20.cn

    前台代码:

    github.com/webim
    2656618087
        38
    2656618087  
    OP
       2013-07-29 09:38:04 +08:00
    这几天看了看,还是决定用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  
       2013-07-29 09:54:55 +08:00
    socket.io 天生就好像是为了 聊天室而生。。 楼主 为何不试试看
    davepkxxx
        40
    davepkxxx  
       2013-07-29 10:10:03 +08:00
    dwr是通 过长连接+定时断开重连 来实现的,如果你不想手动做这个事情,那么用dwr是最好的选择了,或者你也可以选择flash(不少移动浏览器不支持)、html5(ie6~8不支持)、awt(需要客户安装jar)来实现。
    isayme
        41
    isayme  
       2013-07-29 10:33:07 +08:00
    tlk.io好像是nodejs+socket.io做的,目测很不错
    wity_lv
        42
    wity_lv  
       2013-07-29 11:18:07 +08:00
    @2656618087 我想说,你在重造轮子。node.js 的 socket.io 模块已经把Pub/Sub这个事情处理的很好。
    如果你专注于技术学习,可以用servlet 3.0试试。 第一步需要使用底层api实现一个pub/sub模型,之后再基于这层进行聊天室的开发。
    2656618087
        43
    2656618087  
    OP
       2013-07-29 15:33:57 +08:00
    这么说大概明白了。谢谢你 @wity_lv @isayme @davepkxxx @thursday
    照你说我那样做除了麻烦费事,其实也是可行的对不?我这个试完了 研究研究 socket.io 和 dwr 再次感谢。
    wity_lv
        44
    wity_lv  
       2013-07-29 16:19:58 +08:00
    @2656618087 折腾吧,当时我也折腾过,后来选择了pushlet, 现在用socket.io.
    Actrace
        45
    Actrace  
       2013-07-29 20:19:30 +08:00
    最近折腾了一个Ajax Online Chat Demo,楼主可以看看.
    http://try.maxfs.org
    几乎实时.
    Actrace
        46
    Actrace  
       2013-07-29 20:20:01 +08:00
    地址错了,补充一下.
    http://try.maxfs.org/chat.php
    xdyl
        47
    xdyl  
       2013-07-30 11:17:06 +08:00
    http://www.ptteng.com

    WebSocket实现的.
    gracechen
        48
    gracechen  
       2013-08-03 20:49:26 +08:00
    楼主有兴趣我们邮件联系?[email protected]
    gracechen
        49
    gracechen  
       2013-08-03 20:50:00 +08:00
    忘记问。。楼主和@nybux 在帝都吗?
    nybux
        50
    nybux  
       2013-08-04 08:00:45 +08:00
    @gracechen 魔都
    gagahjt
        51
    gagahjt  
       2013-08-06 15:52:57 +08:00
    nodejs+socket.io 做压力测试有什么好的方法和工具么?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1059 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 18:25 PVG 02:25 LAX 11:25 JFK 14:25
    Do have aith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86