公司刚好让做即时通讯模块,服务器使用openfire,偶然看到有位仁兄的帖子,拷贝过来细细研究,感谢此仁兄的无私,期待此仁兄的下次更新

转自http://blog.csdn.net/lnb333666/article/details/7476177

Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】

废话少说,公司没事干,组长叫我写Demo,我狂晕....

先把先说说这个什么聊天室吧,服务器就别说了,典型的拿来主义。用的是成品的openfire。说道smack,这个是一个jar文件,库,是用在javae的。要想在android端使用这个,就要用到asmack包,这个可以在官网下。其实里边跟smack包没什么区别,具体差异目前我没发现。

可能有的朋友说这个smack是什么用的,我个人一句话,一个已经包装了XMPP协议的架包。提供了API的操作...好了进入正题

1,首先想进入聊天室,那必须要先知道聊天室所在的会议服务(下图,用spark截图)

[java] view plaincopyprint?
  1. /**
  2. * 初始化聊服务会议列表
  3. */
  4. private void initHostRoom() {
  5. Collection<HostedRoom> hostrooms;
  6. try {
  7. hostrooms = MultiUserChat.getHostedRooms(Constants.conn,
  8. Constants.conn.getServiceName());
  9. for (HostedRoom entry : hostrooms) {
  10. roominfos.add(entry);
  11. Log.i(TAG, "名字:" + entry.getName() + " - ID:" + entry.getJid());
  12. }
  13. Log.i(TAG, "服务会议数量:" + roominfos.size());
  14. } catch (XMPPException e) {
  15. e.printStackTrace();
  16. }
  17. }

2,获取了那个服务的JID后才能进入会议列表:

[java] view plaincopyprint?
  1. /**
  2. * 初始化房间列表
  3. */
  4. public void init() {
  5. listDiscoverItems = new ArrayList<DiscoverItems.Item>();
  6. // 获得与XMPPConnection相关的ServiceDiscoveryManager
  7. ServiceDiscoveryManager discoManager = ServiceDiscoveryManager
  8. .getInstanceFor(Constants.conn);
  9. // 获得指定XMPP实体的项目
  10. // 这个例子获得与在线目录服务相关的项目
  11. DiscoverItems discoItems;
  12. try {
  13. discoItems = discoManager.discoverItems(jid);
  14. // 获得被查询的XMPP实体的要查看的项目
  15. Iterator it = discoItems.getItems();
  16. // 显示远端XMPP实体的项目
  17. while (it.hasNext()) {
  18. DiscoverItems.Item item = (DiscoverItems.Item) it.next();
  19. System.out.println(item.getEntityID());
  20. System.out.println(item.getName());
  21. listDiscoverItems.add(item);
  22. }
  23. } catch (XMPPException e) {
  24. e.printStackTrace();
  25. }
  26. }

3,同样,要进入会议房间(聊天室)也要获取它的ID,才能进入

[java] view plaincopyprint?
  1. // 后面服务名称必需是创建房间的那个服务
  2. jid = getIntent().getStringExtra("jid");
  3. try {
  4. muc = new MultiUserChat(Constants.conn, jid);
  5. // 创建聊天室,进入房间后的nickname(昵称)
  6. muc.join("痞子测试");
  7. Log.v(TAG, "join success");
  8. } catch (XMPPException e) {
  9. e.printStackTrace();
  10. }

简单吧!

Android基于XMPP Smack openfire 开发的聊天室(二) 【聊天信息、成员】

上一篇呢说了怎么进入这个聊天室,这次呢,咱就说聊天室里的功能吧,聊天信息、成员变动什么的。还是少说废话,正题:

1,说要聊天呢,简单就是一个文本信息,当然我们不能时时去服务器获取信息。要充分发挥即时推送嘛。

(1)首先要添加一个监听,muc.addMessageListener(chatListener);   要是muc不知道是什么请看上一篇吧,这就不多解释。chatListener就是我们的监听器,看代码,其实下边的代码有些啰嗦。我只是懒得改了。最近有点烦躁。这里我们主要获取的就是Packet,这个是一个XMPP包装好的XML流,里边有你想要的东西。有兴趣深入的朋友可以上XMPP中文翻译组去看看,挺犀利的。

[java] view plaincopyprint?
  1. /**
  2. * PacketListener 通过一个规定的过滤器提供一个机制来监听数据包
  3. *
  4. * @author liaonaibo
  5. *
  6. */
  7. class ChatPacketListener implements PacketListener {
  8. private String _number;
  9. private Date _lastDate;
  10. private MultiUserChat _muc;
  11. private String _roomName;
  12. public ChatPacketListener(MultiUserChat muc) {
  13. _number = "0";
  14. _lastDate = new Date(0);
  15. _muc = muc;
  16. _roomName = muc.getRoom();
  17. }
  18. @Override
  19. public void processPacket(Packet packet) {
  20. Message message = (Message) packet;
  21. String from = message.getFrom();
  22. if (message.getBody() != null) {
  23. DelayInformation inf = (DelayInformation) message.getExtension(
  24. "x", "jabber:x:delay");
  25. Date sentDate;
  26. if (inf != null) {
  27. sentDate = inf.getStamp();
  28. } else {
  29. sentDate = new Date();
  30. }
  31. Log.i(TAG, "Receive old message: date="
  32. + sentDate.toLocaleString() + " ; message="
  33. + message.getBody());
  34. android.os.Message msg = new android.os.Message();
  35. msg.what = RECEIVE;
  36. Bundle bd = new Bundle();
  37. bd.putString("from", from);
  38. bd.putString("body", message.getBody());
  39. msg.setData(bd);
  40. handler.sendMessage(msg);
  41. }
  42. }
  43. }

2,下边就是成员了,一个聊天室没成员多离谱的事情啊,我们主要做的是把成员列表逃出来。其实有几种方法可以弄出来的,我只是简单的获取成员的昵称。可能有朋友会问为什么不获取成员的信息呢。这个下一篇我会告诉你。

[java] view plaincopyprint?
  1. /**
  2. * 获取聊天室的所有成员
  3. */
  4. private void getAllMember() {
  5. Log.i(TAG, "获取聊天室的所有成员");
  6. affiliates.clear();
  7. new Thread(new Runnable() {
  8. @Override
  9. public void run() {
  10. try {
  11. Iterator<String> it = muc.getOccupants();
  12. while (it.hasNext()) {
  13. String name = it.next();
  14. name = name.substring(name.indexOf("/") + 1);
  15. affiliates.add(name);
  16. Log.i(TAG, "成员名字;" + name);
  17. }
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. android.os.Message msg = new android.os.Message();
  22. msg.what = MEMBER;
  23. handler.sendMessage(msg);
  24. }
  25. }).start();
  26. }

这篇结束,下篇写写聊天室的一些权限的变更、成员的变更、主题变更什么的。

Android基于XMPP Smack openfire 开发的聊天室(三) 【新旧记录、踢人】

1,聊天室新旧消息的记录,先看看一段服务器返回的XML吧

[html] view plaincopyprint?
  1. <message
  2. from='darkcave@chat.shakespeare.lit/firstwitch'
  3. to='hecate@shakespeare.lit/broom'
  4. type='groupchat'>
  5. <body>Thrice the brinded cat hath mew'd.</body>
  6. <delay xmlns='urn:xmpp:delay'
  7. from='crone1@shakespeare.lit/desktop'
  8. stamp='2002-10-13T23:58:37Z'/>
  9. </message>
  10. <message
  11. from='darkcave@chat.shakespeare.lit/secondwitch'
  12. to='hecate@shakespeare.lit/broom'
  13. type='groupchat'>
  14. <body>Thrice and once the hedge-pig whined.</body>
  15. <delay xmlns='urn:xmpp:delay'
  16. from='wiccarocks@shakespeare.lit/laptop'
  17. stamp='2002-10-13T23:58:43Z'/>
  18. </message>
  19. <message
  20. from='darkcave@chat.shakespeare.lit/thirdwitch'
  21. to='hecate@shakespeare.lit/broom'
  22. type='groupchat'>
  23. <body>Harpier cries 'Tis time, 'tis time.</body>
  24. <delay xmlns='urn:xmpp:delay'
  25. from='hag66@shakespeare.lit/pda'
  26. stamp='2002-10-13T23:58:49Z'/>
  27. </message>

上边这段是一个聊天室返回的XML数据,是历史消息。就在这里要告诉大家的是,如果是新消息的话就没有<delay>节点。所以我们以这个为根据来判断。下边贴些我的代码,因为服务器被我们给改了,所以返回的有些出入。但八九不离十。原理一样。

[java] view plaincopyprint?
  1. DelayInformation inf = (DelayInformation) message.getExtension(
  2. "x", "jabber:x:delay");
  3. System.out.println("判断消息");
  4. if (inf == null && count >= 1) {
  5. System.out.println("新消息来了");
  6. isHistory = true;
  7. } else {
  8. System.out.println("这是旧的消息");
  9. }

这段代码写哪里呢,就是写在消息的监听里头

[java] view plaincopyprint?
  1. /**
  2. * PacketListener 通过一个规定的过滤器提供一个机制来监听数据包
  3. *
  4. * @author liaonaibo
  5. *
  6. */
  7. class ChatPacketListener implements PacketListener

重写它的方法

[java] view plaincopyprint?
  1. @Override
  2. public void processPacket(Packet packet)

好了,下边讲踢人吧

2,踢人:

踢人很简单,只要你是房主,或管理员什么的,主持人也行。这些高权限的才能有踢人的权限。

[java] view plaincopyprint?
  1. // 踢人
  2. try {
  3. String nickName = affiliates.get(id);
  4. //得到的昵称包含的房间名和服务名的一段很长数据。好像是吧。哈哈,忘记了。所以截取吧
  5. muc.kickParticipant(nickName
  6. .substring(nickName.indexOf("]") + 1), "看你不爽就 踢了你");
  7. android.os.Message msg = new android.os.Message();
  8. msg.what = MEMBER;
  9. handler.sendMessage(msg);
  10. Toast.makeText(this, "哈哈,踹了你", Toast.LENGTH_LONG).show();
  11. } catch (XMPPException e) {
  12. e.printStackTrace();
  13. Toast.makeText(this, "你没有权利踢人", Toast.LENGTH_LONG).show();
  14. }

有的哥们会疑惑,说如果根据昵称来踢人,那会不会把重名的人都一起踢了。这个问题我也想过,这个也是测试的一个弊端。但是如果通过spark来看,即便你用同样的名字加入了房间,要么会报错,要么就是系统自动在你的名字后边加个2,呵呵,够2吧。如果有人坚持要用自己的昵称,这个可以的,具体怎么样做,下次再阐述。

Android基于XMPP Smack openfire 开发的聊天室(四) 【创建房间、表单;报文】

这篇就主要讲创建房间和报文吧。

1,创建房间:

其实创建房间很简单,两句话就搞定了。但你要知道,简单的同时,服务器可没帮你配置房间的信息什么的。所以一般用下边的方法来创建房间别人是进不去的。

[java] view plaincopyprint?
  1. // 使用XMPPConnection创建一个MultiUserChat
  2. MultiUserChat muc = new MultiUserChat(conn1, "myroom@conference.jabber.org");
  3. //创建聊天室
  4. muc.create("testbot");
  5. // 发送一个空表单配置这显示我们想要一个instant room
  6. muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));

所以咱们还是手动配置一些信息吧,免得留后患。不过在这里要给朋友们提个醒,我觉得不论是哪种方法都很狗屎,为什么狗屎。你看看那MUC,本来就是一个聊天室了,还要让你在聊天室创建另个聊天室,老妈生孩子,然后孩子和老妈并排。狗屎啊,不过不排除我理解错误。希望高人能给与指点。

[java] view plaincopyprint?
  1. try {
  2. // 创建聊天室
  3. muc.create(Constants.vCard.getNickName().toString());
  4. // 获得聊天室的配置表单
  5. Form form = muc.getConfigurationForm();
  6. // 根据原始表单创建一个要提交的新表单。
  7. Form submitForm = form.createAnswerForm();
  8. // 向要提交的表单添加默认答复
  9. for (Iterator fields = form.getFields(); fields.hasNext();) {
  10. FormField field = (FormField) fields.next();
  11. if (!FormField.TYPE_HIDDEN.equals(field.getType())
  12. && field.getVariable() != null) {
  13. // 设置默认值作为答复
  14. submitForm.setDefaultAnswer(field.getVariable());
  15. }
  16. }
  17. // 设置聊天室的新拥有者
  18. // List owners = new ArrayList();
  19. // owners.add("liaonaibo2\\40slook.cc");
  20. // owners.add("liaonaibo1\\40slook.cc");
  21. // submitForm.setAnswer("muc#roomconfig_roomowners", owners);
  22. // 设置聊天室是持久聊天室,即将要被保存下来
  23. submitForm.setAnswer("muc#roomconfig_persistentroom", true);
  24. // 房间仅对成员开放
  25. submitForm.setAnswer("muc#roomconfig_membersonly", false);
  26. // 允许占有者邀请其他人
  27. submitForm.setAnswer("muc#roomconfig_allowinvites", true);
  28. // 能够发现占有者真实 JID 的角色
  29. // submitForm.setAnswer("muc#roomconfig_whois", "anyone");
  30. // 登录房间对话
  31. submitForm.setAnswer("muc#roomconfig_enablelogging", true);
  32. // 仅允许注册的昵称登录
  33. submitForm.setAnswer("x-muc#roomconfig_reservednick", true);
  34. // 允许使用者修改昵称
  35. submitForm.setAnswer("x-muc#roomconfig_canchangenick", false);
  36. // 允许用户注册房间
  37. submitForm.setAnswer("x-muc#roomconfig_registration", false);
  38. // 发送已完成的表单(有默认值)到服务器来配置聊天室
  39. muc.sendConfigurationForm(submitForm);
  40. } catch (XMPPException e) {
  41. e.printStackTrace();
  42. }

还有个细节,有朋友估计看到我注释的那里有\\40的代码。原因是在XMPP中的唯一标示JID不允许出现@,所以要转义。OK?

2,报文
有朋友说报文干嘛,其实我开始也觉得有点多余,但想想类似QQ群那样,人下线了,头像名字变灰色。如果是openfire服务器的话,你下线了就直接把你去除。所以我们要给服务器发送个广播。具体处理那是以后的是了。看看这段报文:

[html] view plaincopyprint?
  1. <iq id="902U0-48" type="set">
  2. <query xmlns="jabber:iq:private">
  3. <storage xmlns="storage:bookmarks">
  4. <conference name="ccc" autojoin="true" jid="ccc@conference.xmpp.chaoboo.com" ></conference>
  5. </storage>
  6. </query>
  7. </iq>

报文可以根据需要来改服务器的插件。

下边发送的报文:

[java] view plaincopyprint?
  1. /**
  2. * 用户加入时向服务器发送的报文
  3. * @return
  4. */
  5. public IQ joinXml(){
  6. IQ iq = new IQ() {
  7. public String getChildElementXML() {
  8. StringBuilder buf = new StringBuilder();
  9. buf.append("<query xmlns=\"jabber:iq:private\">");
  10. buf.append("<storage xmlns=\"storage:bookmarks\">");
  11. buf.append("<").append("conference").append(" name=\"ccc\"").append(" autojoin=\"false\"").append("");
  12. buf.append("</storage>");
  13. buf.append("</query>");
  14. return buf.toString();
  15. }
  16. };
  17. iq.setType(IQ.Type.SET);
  18. //方法如名,这里是设置这份报文来至那个JID,后边的/smack是这段信息来至哪个端,如spark端就是/spark,android就是/Smack
  19. iq.setFrom(Constants.USERNAME+"@naibo.liao.com/Smack");
  20. return iq;
  21. }

怎么发送呢?可以通过连接,就是XMPPCONNECTION来发送:

[java] view plaincopyprint?
  1. Constants.conn.sendPacket(leaveXml());

OK,停一会,手酸了

Android基于XMPP Smack openfire 开发的聊天室(五) 【邀请、被邀请】

1,邀请:

很简单的一句话,邀请的时候要传入被邀请者的JID,邀请信息可以为空。

[java] view plaincopyprint?
  1. muc.invite(userjid, "进来我们聊妹子");

简单的同时我们要知道它发生了什么,当这句话执行会向服务器发送一段报文,如下:

[html] view plaincopyprint?
  1. <message
  2. from='crone1@shakespeare.lit/desktop'
  3. to='darkcave@chat.shakespeare.lit'>
  4. <x xmlns='http://jabber.org/protocol/muc#user'>
  5. <invite to='hecate@shakespeare.lit'>
  6. <reason>
  7. 进来我们聊妹子
  8. </reason>
  9. </invite>
  10. </x>
  11. </message>

2,被邀请

被邀请呢,我们可以开个监听吧,要不要进房间先不判断了,我这里如果有邀请就直接进房间。有需要的朋友可以自己琢磨:

[java] view plaincopyprint?
  1. MultiUserChat.addInvitationListener(Constants.conn,
  2. new InvitationListener() {
  3. // 对应参数:连接、 房间JID、房间名、附带内容、密码、消息
  4. @Override
  5. public void invitationReceived(Connection conn,
  6. String room, String inviter, String reason,
  7. String password, Message message) {
  8. Log.i(TAG, "收到来自 " + inviter + " 的聊天室邀请。邀请附带内容:"
  9. + reason);
  10. Intent intent = new Intent(MucService.this,
  11. ActivityMultiRoom.class);
  12. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  13. intent.putExtra("jid", room);
  14. intent.putExtra("action", "join");
  15. startActivity(intent);
  16. }
  17. });

Android基于XMPP Smack openfire 开发的聊天室(六) 【加入房间、权限错误】

1,加入房间错误,通常一个就是密码错误。此时服务器会返回以下报文:

[html] view plaincopyprint?
  1. <presence
  2. from='darkcave@chat.shakespeare.lit'
  3. to='hag66@shakespeare.lit/pda'
  4. type='error'>
  5. <x xmlns='http://jabber.org/protocol/muc'/>
  6. <error type='auth'>
  7. <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  8. </error>
  9. </presence>

官网意思:如果房间要求密码验证而用户不能提供(或密码错误), 服务必须 MUST 拒绝访问这个房间并且通知该用户它们是未被授权的; 具体方法是返回一个类型为"error"的出席信息节并标明 <not-authorized/> 错误

解决如下:

[java] view plaincopyprint?
  1. // 使用XMPPConnection创建一个MultiUserChat
  2. MultiUserChat muc2 = new MultiUserChat(conn1,
  3. "myroom@chat.shakespeare.lit/thirdwitch");
  4. // 用户2使用密码加入新聊天室
  5. // 聊天室服务将会决定要发送的历史记录数量
  6. muc2.join("testbot2", "password");

报文如下:

[html] view plaincopyprint?
  1. <presence
  2. from='hag66@shakespeare.lit/pda'
  3. to='myroom@chat.shakespeare.lit/thirdwitch'>
  4. <x xmlns='http://jabber.org/protocol/muc'>
  5. <password>password</password>
  6. </x>
  7. </presence>

2,权限错误:

这个没文本,当然如果你加入一个房间后,要注意的是,如果第一次加入别人的房间,没有被授予成员权限的时候,你仅仅是一个游客。除了说话。也不能检索聊天室成员的信息,仅可以获取成员的昵称,除此别无其他。通常不注意会用这样贸然去获取成员信息是,会照成错误,返回402(进入房间后获取超越权限错误:权限不足)等信息。以下是其他错误信息

401 Error Presence  进入一个房间

通知用户需要密码

403 Error Presence  进入一个房间 通知用户他或她被房间禁止了
404 Error Presence  进入一个房间 通知用户房间不存在
405 Error Presence  进入一个房间 通知用户限制创建房间
406 Error Presence  进入一个房间 通知用户必须使用保留的房间昵称
407 Error Presence  进入一个房间 通知用户他或她不在成员列表中
409 Error Presence  进入一个房间 通知用户他或她的房间昵称正在使用或被别的用户注册了
503 Error Presence  进入一个房间 通知用户已经达到最大用户数

用户聊天的使用一个 <status/> 元素(特指, <status/> 元素的的 'code' 属性  ) 来传达关于用户在一个房间里的状态的信息.

Android基于XMPP Smack openfire 开发的聊天室(七) 【成员状态、自身状态】

1,聊天是成员的监听,加到MUC里边就行

[java] view plaincopyprint?
  1. /**
  2. * 聊天室成员的监听器
  3. *
  4. * @author 廖乃波
  5. *
  6. */
  7. class MyParticipantStatusListener implements ParticipantStatusListener {
  8. @Override
  9. public void adminGranted(String arg0) {
  10. Log.i(TAG, "授予管理员权限" + arg0);
  11. }
  12. @Override
  13. public void adminRevoked(String arg0) {
  14. Log.i(TAG, "移除管理员权限" + arg0);
  15. }
  16. @Override
  17. public void banned(String arg0, String arg1, String arg2) {
  18. Log.i(TAG, "禁止加入房间(拉黑,不知道怎么理解,呵呵)" + arg0);
  19. }
  20. @Override
  21. public void joined(String arg0) {
  22. Log.i(TAG, "执行了joined方法:" + arg0 + "加入了房间");
  23. // 更新成员
  24. getAllMember();
  25. android.os.Message msg = new android.os.Message();
  26. msg.what = MEMBER;
  27. handler.sendMessage(msg);
  28. }
  29. @Override
  30. public void kicked(String arg0, String arg1, String arg2) {
  31. Log.i(TAG, "踢人" + arg0 + "被踢出房间");
  32. }
  33. @Override
  34. public void left(String arg0) {
  35. String lefter = arg0.substring(arg0.indexOf("/") + 1);
  36. Log.i(TAG, "执行了left方法:" + lefter + "离开的房间");
  37. // 更新成员
  38. getAllMember();
  39. android.os.Message msg = new android.os.Message();
  40. msg.what = MEMBER;
  41. handler.sendMessage(msg);
  42. }
  43. @Override
  44. public void membershipGranted(String arg0) {
  45. Log.i(TAG, "授予成员权限" + arg0);
  46. }
  47. @Override
  48. public void membershipRevoked(String arg0) {
  49. Log.i(TAG, "成员权限被移除" + arg0);
  50. }
  51. @Override
  52. public void moderatorGranted(String arg0) {
  53. Log.i(TAG, "授予主持人权限" + arg0);
  54. }
  55. @Override
  56. public void moderatorRevoked(String arg0) {
  57. Log.i(TAG, "移除主持人权限" + arg0);
  58. }
  59. @Override
  60. public void nicknameChanged(String arg0, String arg1) {
  61. Log.i(TAG, "昵称改变了" + arg0);
  62. }
  63. @Override
  64. public void ownershipGranted(String arg0) {
  65. Log.i(TAG, "授予所有者权限" + arg0);
  66. }
  67. @Override
  68. public void ownershipRevoked(String arg0) {
  69. Log.i(TAG, "移除所有者权限" + arg0);
  70. }
  71. @Override
  72. public void voiceGranted(String arg0) {
  73. Log.i(TAG, "给" + arg0+"授权发言");
  74. }
  75. @Override
  76. public void voiceRevoked(String arg0) {
  77. Log.i(TAG, "禁止" + arg0+"发言");
  78. }
  79. }

2,自身状态监听

[java] view plaincopyprint?
  1. class MyUserStatusListener  implements UserStatusListener {
  2. /*这里实现默认方法即可*/
  3. }

都一样,看不懂可以有道翻译,累了,睡觉先。

Android基于XMPP Smack openfire 开发的聊天室相关推荐

  1. Android基于XMPP Smack Openfire开发IM(5)发送消息

    这节到重点了,看看发送消息的实现,代码写的很简单,主要为了演示功能的实现, 废话不说了. 在登陆以后应该建立一个监听消息的监听器,用来监听收到的消息: 这里收到消息后,通过广播将消息发送到需要的地方, ...

  2. Android基于XMPP Smack Openfire下学习开发IM(二)对分组、好友和头像等一些操作

    下面就一起来学习一下,如何查询分组和添加分组等! 一.查询所有分组 通过Roster来获取所有分组,Roster可以通过connection.getRoster()来得到. /*** 获取所有组* * ...

  3. Android基于环信SDK开发IM即时聊天(一)

    2016-09-02更新:可以看一下最新的这篇文章和源码,Android基于环信SDK开发IM即时聊天(二) 目前市面上我了解的做第三方即时聊天SDK的有两家:环信.融云,这里我使用环信SDK来完成即 ...

  4. Android基于环信SDK开发IM即时聊天(二)

    声明1:北京时间现在是2019/6/10,评论里的问题我看到了,这几天我找时间看看源代码问题出在哪,在此感谢大家的监督 声明2:此Demo我是在5.1测试机上测试通过,感谢WTQ_DOMIAN的评论, ...

  5. 基于 vue.js 的仿QQ聊天室

    简介 这是一款基于 vue.js 开发的聊天室组件库,在提供基础封装的同时,最大程度的增加扩展性. 下面是效果演示图: MChat组件效果图: IChat组件效果图: 如何安装 使用 npm 安装 n ...

  6. 【java毕业设计】基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码)——聊天室系统

    基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+原生Sevlet+socket的聊天室系统设计与实现,文章末尾附有本毕业设 ...

  7. java毕业设计——基于java+TCP+UDP的局域网聊天室系统设计与实现(毕业论文+程序源码)——局域网聊天室系统

    基于java+TCP+UDP的局域网聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+TCP+UDP的局域网聊天室系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地 ...

  8. 基于Socket通信的在线网络聊天室

    文章目录 项目结构 client constans entity util IO server ui other 大致思路 演示 时间:2021/4/20 开发环境: jdk1.8 编译器:idea2 ...

  9. Java和WebSocket开发网页聊天室

    一.项目简介 WebSocket是HTML5一种新的协议,它实现了浏览器与服务器全双工通信,这里就将使用WebSocket来开发网页聊天室,前端框架会使用AmazeUI,后台使用Java,编辑器使用U ...

最新文章

  1. Python Qt GUI设计:将UI文件转换为Python文件的三种妙招(基础篇—2)
  2. SpringCloud实战4-Hystrix线程隔离请求缓存请求合并
  3. 【转】主要空间数据挖掘方法
  4. 服务器一键建php网站,搭建服务器 - 我的lnmp一键安装报错 - php中文网博客
  5. DefaultNetworkCredentials vs DefaultCredentials
  6. python进程数上限_在多处理python中限制进程数
  7. 分析:微软最终将赢得平板电脑市场的5个理由
  8. .net知识和学习方法系列(二十一)CLR-枚举
  9. HDU5926 Mr. Frog’s Game
  10. VirtualBox安装MACOSX 10.13虚拟机的增强功能
  11. linux 系统tty、pty和pts 的概念及区别
  12. 简单高效,分享几款我在使用的效率神器
  13. java项目如何打包?
  14. 【ps功能精通】6.钢笔工具
  15. Epub电子书的格式(二)
  16. Allegro中 设置指定的网络线宽的方法
  17. mac 打开网页慢_在Mac电脑开启Safari速度总是很慢?可以试试这10种解决方法
  18. loaderrunner11.00安装与破解
  19. 网络协议和Netty(4):大白话说三次握手及用一个数据库连接解释三次握手
  20. 如何使用Logitech Harmony遥控器控制智能家居设备

热门文章

  1. 教你利用python画画
  2. Go语言 大话数据结构——图
  3. NOIP simulation
  4. git merge squash 和 rebase 区别
  5. 论文浏览(27) Long-Term Feature Banks for Detailed Video Understanding
  6. UBT17:ubuntu安装NotePadqq
  7. Python爬虫之——爬取妹子图片
  8. springboot汽车配件销售系统-预约洗车系统java
  9. 初来咋到的,多多关照哈~
  10. graphpad分组百分比柱状图_如何用GraphPad Prism 8.0绘制分组散点图与柱状图共存图?...