xmpp-多人聊天实例

更新时间:2024-04-13 05:47:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

一直想写东西,但是上班不能在CSDN上写东西。下班回家又忙着学Iphone开发,唉,两个个字,忒忙。今天就写写Smack的聊天室功能吧。 先上代码:

view plain

1. import java.io.BufferedReader; 2. import java.io.InputStreamReader; 3. import java.util.ArrayList; 4. import java.util.Collection; 5. import java.util.Iterator; 6. import java.util.List; 7.

8. import org.jivesoftware.smack.Chat;

9. import org.jivesoftware.smack.ConnectionConfiguration; 10. import org.jivesoftware.smack.MessageListener; 11. import org.jivesoftware.smack.PacketListener; 12. import org.jivesoftware.smack.SmackConfiguration; 13. import org.jivesoftware.smack.XMPPConnection; 14. import org.jivesoftware.smack.XMPPException; 15. import org.jivesoftware.smack.packet.Message; 16. import org.jivesoftware.smack.packet.Packet;

17. import org.jivesoftware.smack.provider.ProviderManager; 18. import org.jivesoftware.smackx.Form; 19. import org.jivesoftware.smackx.FormField;

20. import org.jivesoftware.smackx.ServiceDiscoveryManager;

21. import org.jivesoftware.smackx.muc.DefaultParticipantStatusListener; 22. import org.jivesoftware.smackx.muc.DefaultUserStatusListener; 23. import org.jivesoftware.smackx.muc.DiscussionHistory; 24. import org.jivesoftware.smackx.muc.HostedRoom;

25. import org.jivesoftware.smackx.muc.InvitationListener;

26. import org.jivesoftware.smackx.muc.InvitationRejectionListener; 27. import org.jivesoftware.smackx.muc.MultiUserChat; 28. import org.jivesoftware.smackx.muc.RoomInfo;

29. import org.jivesoftware.smackx.muc.SubjectUpdatedListener; 30. import org.jivesoftware.smackx.packet.ChatStateExtension; 31. import org.jivesoftware.smackx.packet.DiscoverInfo; 32. import org.jivesoftware.smackx.packet.DiscoverItems; 33. import org.jivesoftware.smackx.packet.OfflineMessageInfo; 34. import org.jivesoftware.smackx.packet.OfflineMessageRequest; 35. import org.jivesoftware.smackx.provider.AdHocCommandDataProvider; 36. import org.jivesoftware.smackx.provider.BytestreamsProvider; 37. import org.jivesoftware.smackx.provider.DataFormProvider;

38. import org.jivesoftware.smackx.provider.DiscoverInfoProvider; 39. import org.jivesoftware.smackx.provider.DiscoverItemsProvider; 40. import org.jivesoftware.smackx.provider.IBBProviders; 41. import org.jivesoftware.smackx.provider.MUCAdminProvider; 42. import org.jivesoftware.smackx.provider.MUCOwnerProvider; 43. import org.jivesoftware.smackx.provider.MUCUserProvider;

44. import org.jivesoftware.smackx.provider.StreamInitiationProvider; 45. import org.jivesoftware.smackx.provider.VCardProvider;

46. import org.jivesoftware.smackx.provider.XHTMLExtensionProvider; 47.

48. public class TestSmack2 {

49. public static void main(String[] args) {XMPPConnection.DEBUG_ENABLED = true; 50. final ConnectionConfiguration connectionConfig = new ConnectionConfiguration(\

PC2010102716\, 5222, \);

51. connectionConfig.setSASLAuthenticationEnabled(false); 52. ProviderManager pm = ProviderManager.getInstance(); 53. configure(pm); 54. try {

55. XMPPConnection connection = new XMPPConnection(connectionConfig); 56. connection.connect();//连接 57. initFeatures(connection);

58. connection.login(\, \);//登陆 59. //聊天室

60. //MultiUserChat multiUserChat = new MultiUserChat(connection, new Invitati

onListener() {}); 61. //查找服务

62. System.out.println(connection.getServiceName());

63. List col = getConferenceServices(connection.getServiceName(), conn

ection);

64. for (Object aCol : col) {

65. String service = (String) aCol; 66. //查询服务器上的聊天室

67. Collection rooms = MultiUserChat.getHostedRooms(connection

, service);

68. for(HostedRoom room : rooms) { 69. //查看Room消息

70. System.out.println(room.getName() + \ +room.getJid()); 71. RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, room.get

Jid());

72. if(roomInfo != null) {

73. System.out.println(roomInfo.getOccupantsCount() + \ + room

Info.getSubject()); 74. } 75. }

76. } 77.

78. /*---创建默认配置的聊天室 --- 79. 先看看官方的文档:

80. Creates a new multi user chat with the specified connection and room name.

Note: no

81. * information is sent to or received from the server until you attem

pt to

82. * {@link #join(String) join} the chat room. On some server implementa

tions,

83. * the room will not be created until the first person joins it 84. * 最重要一句:直到用户调用join方法的时候聊天室才会被创建 85. */

86. MultiUserChat muc = new MultiUserChat(connection, \

10102716\);

87. muc.create(\);

88. muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT)); 89.

90. //----创建手动配置聊天室----

91. muc = new MultiUserChat(connection, \);

92.

93. //销毁聊天室

94. //muc.destroy(\ 95. muc.create(\); 96. //获取聊天室的配置表单

97. Form form = muc.getConfigurationForm(); 98. //根据原始表单创建一个要提交的新表单

99. Form submitForm = form.createAnswerForm(); 100. //向提交的表单添加默认答复

101. for(Iterator fields = form.getFields(); fields.hasNext();) { 102. FormField field = (FormField) fields.next();

103. if(!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable

() != null) {

104. submitForm.setDefaultAnswer(field.getVariable()); 105. } 106. }

107. //重新设置聊天室名称

108. submitForm.setAnswer(\, \); 109. //设置聊天室的新拥有者

110. List owners = new ArrayList(); 111. owners.add(\);

112. submitForm.setAnswer(\, owners); 113. //设置密码

114. submitForm.setAnswer(\, true); 115. submitForm.setAnswer(\, \); 116. //设置描述

117. submitForm.setAnswer(\, \新创建的reserved聊天室

\);

118. //设置聊天室是持久聊天室,即将要被保存下来

119. //submitForm.setAnswer(\ 120. //发送已完成的表单到服务器配置聊天室 121. muc.sendConfigurationForm(submitForm); 122.

123. //加入聊天室(使用昵称喝醉的毛毛虫 ,使用密码ddd)

124. muc = new MultiUserChat(connection, \); 125. muc.join(\喝醉的毛毛虫\, \); 126.

127. //监听消息

128. muc.addMessageListener(new PacketListener() { 129. @Override

130. public void processPacket(Packet packet) { 131. Message message = (Message) packet;

132. System.out.println(message.getFrom() + \ + message.getBody());

;

133. } 134. }); 135.

136. //muc = new MultiUserChat(connection, \ 137. //muc.join(\喝醉的毛毛虫\ 138.

139. //加入聊天室(使用昵称喝醉的毛毛虫 ,使用密码ddd)并且获取聊天室里最后5条信息, 140. //注:addMessageListener监听器必须在此join方法之前,否则无法监听到需要的5条消

141. muc = new MultiUserChat(connection, \); 142. DiscussionHistory history = new DiscussionHistory(); 143. history.setMaxStanzas(5); 144. muc.join(\喝醉的毛毛虫

\, \, history, SmackConfiguration.getPacketReplyTimeout()); 145.

146. //监听拒绝加入聊天室的用户

147. muc.addInvitationRejectionListener(new InvitationRejectionListener() { 148. @Override

149. public void invitationDeclined(String invitee, String reason) { 150. System.out.println(invitee + \ + reason

);

151. } 152. });

153. //邀请用户加入聊天室

154. muc.invite(\, \大家来谈谈人生\); 155. //监听邀请加入聊天室请求

156. MultiUserChat.addInvitationListener(connection, new InvitationListener() {

157. @Override

158. public void invitationReceived(XMPPConnection conn, String room, Strin

g inviter, String reason, String password, Message message) { 159. //例:直接拒绝邀请

160. MultiUserChat.decline(conn, room, inviter, \你丫很闲啊!\); 161. } 162. }); 163. 164.

165. //根据roomJID获取聊天室信息

166. RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, \

pc2010102716\);

167. System.out.println(roomInfo.getRoom() + \ + roomInfo.getSubject() + \

+ roomInfo.getOccupantsCount()); 168.

169. //判断用户是否支持Multi-User聊天协议 170. //注:需要加上资源标识符

171. boolean supports = MultiUserChat.isServiceEnabled(connection, \

0102716/spark\);

172. //获取某用户所加入的聊天室 173. if(supports) {

174. Iterator joinedRooms = MultiUserChat.getJoinedRooms(connection

, \);

175. while(joinedRooms.hasNext()) {

176. System.out.println(\ + joinedRooms.next());

177. } 178. } 179.

180. //与聊天室用户私聊

181. Chat chat = muc.createPrivateChat(\飞鸟

\, new MessageListener() { 182. @Override

183. public void processMessage(Chat chat, Message message) {

184. System.out.println(\ + messa

ge.getFrom() + \ + message.getBody()); 185. } 186. });

187. chat.sendMessage(\今天不用加班吧?\);

188.

189. //改变聊天室主题

190. muc.addSubjectUpdatedListener(new SubjectUpdatedListener() { 191. @Override

192. public void subjectUpdated(String subject, String from) {

193. System.out.println(\ + subject +\ + from)

;

194. } 195. });

196. //muc.changeSubject(\ 197.

198. /*一个成员可能有四种角色:

199. 1:主持者(Moderator) (权限最大的角色,管理其他成员在聊天室中的角色 200. 2:参与者(Participant

201. 3:游客 (Visitor) (不能向所有成员发送消息) 202. 4:无(没有角色)(NONE) 203. */ 204.

205. /*聊天室用户可以有5种从属关系 206. * 1、所有者 Owner 207. * 2、管理员 Admin 208. * 3、成员 Member 209. * 4、被驱逐者 Outcast 210. * 5、无(不存在从属关系) None 211. */ 212.

213. //配置聊天室为Moderated聊天室 214. form = muc.getConfigurationForm();

215. Form answerForm = form.createAnswerForm();

216. answerForm.setAnswer(\, \); 217. muc.sendConfigurationForm(answerForm); 218.

219. //监听自己的状态变更和事件

220. muc.addUserStatusListener(new DefaultUserStatusListener() { 221. @Override

222. public void voiceRevoked() { 223. super.voiceRevoked();

224. System.out.println(\你被禁言了!\); 225. } 226.

227. @Override

228. public void voiceGranted() { 229. super.voiceGranted();

230. System.out.println(\你被批准发言了!\);

231. } 232.

233. @Override

234. public void membershipGranted() { 235. super.membershipGranted();

236. System.out.println(\你被赋予了Member权限\); 237. } 238.

239. @Override

240. public void membershipRevoked() { 241. super.membershipRevoked();

242. System.out.println(\你被解除了Member权限\); 243. } 244.

245. @Override

246. public void adminGranted() { 247. super.adminGranted();

248. System.out.println(\你被赋予了管理员权限\); 249. } 250.

251. @Override

252. public void adminRevoked() { 253. super.adminRevoked();

254. System.out.println(\你被解除了管理员权限\); 255. } 256. //...... 257. });

258. //房主(Owner)批准test3发言权

259. muc.grantVoice(\); 260.

261. //监听他人状态变更

262. muc.addParticipantStatusListener(new DefaultParticipantStatusListener() {

263.

264. @Override

265. public void voiceGranted(String participant) { 266. super.voiceGranted(participant);

267. System.out.println(participant + \被批准发言了!\); 268. } 269.

270. @Override

271. public void voiceRevoked(String participant) { 272. super.voiceRevoked(participant);

273. System.out.println(participant + \被禁言了!\);

274. } 275.

276. @Override

277. public void membershipRevoked(String participant) { 278. super.membershipRevoked(participant); 279. } 280.

281. @Override

282. public void adminGranted(String participant) { 283. super.adminGranted(participant); 284. } 285.

286. @Override

287. public void adminRevoked(String participant) { 288. super.adminRevoked(participant); 289. } 290.

291. }); 292.

293. //房主(Owner)批准test3管理员特权 294. muc.grantAdmin(\); 295. 296.

297. //发送消息

298. BufferedReader cmdIn = new BufferedReader(new InputStreamReader(System.in)

);

299. while(true) { 300. try {

301. String cmd = cmdIn.readLine(); 302. if(\.equalsIgnoreCase(cmd)) { 303. break; 304. }

305. }catch(Exception ex) { 306. } 307. }

308. connection.disconnect(); 309. System.exit(0); 310. } catch (Exception e) { 311. e.printStackTrace(); 312. } 313. } 314.

315. public static List getConferenceServices(String server, XMPPConnection co

nnection) throws Exception {

316. List answer = new ArrayList();

317. ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstance

For(connection);

318. DiscoverItems items = discoManager.discoverItems(server);

319. for (Iterator it = items.getItems(); it.hasNext();) {

320. DiscoverItems.Item item = (DiscoverItems.Item)it.next();

321. if (item.getEntityID().startsWith(\) || item.getEntityID().

startsWith(\)) {

322. answer.add(item.getEntityID()); 323. } 324. else { 325. try {

326. DiscoverInfo info = discoManager.discoverInfo(item.getEntityID

());

327. if (info.containsFeature(\)) {

328. answer.add(item.getEntityID()); 329. } 330. }

331. catch (XMPPException e) { 332. } 333. } 334. }

335. return answer; 336. } 337. 338.

339. private static void configure(ProviderManager pm) { 340. // Service Discovery # Items

341. pm.addIQProvider(\, \, new Discov

erItemsProvider());

342. // Service Discovery # Info

343. pm.addIQProvider(\, \, new Discove

rInfoProvider()); 344.

345. // Service Discovery # Items

346. pm.addIQProvider(\, \, new Discov

erItemsProvider());

347. // Service Discovery # Info

348. pm.addIQProvider(\, \, new Discove

rInfoProvider()); 349.

350. //Offline Message Requests

351. pm.addIQProvider(\,\, new OfflineMe

ssageRequest.Provider());

352. //Offline Message Indicator

353. pm.addExtensionProvider(\,\

, new OfflineMessageInfo.Provider()); 354. 355. //vCard

356. pm.addIQProvider(\,\, new VCardProvider()); 357.

358. //FileTransfer

359. pm.addIQProvider(\,\, new StreamInitiationPro

vider());

360. pm.addIQProvider(\,\, new

BytestreamsProvider());

361. pm.addIQProvider(\,\, new IBBProvi

ders.Open());

362. pm.addIQProvider(\,\, new IBBProv

iders.Close());

363. pm.addExtensionProvider(\,\, new I

BBProviders.Data()); 364. //Data Forms

365. pm.addExtensionProvider(\, \, new DataFormProvider()); 366. //Html

367. pm.addExtensionProvider(\, \, new

XHTMLExtensionProvider()); 368. //Ad-Hoc Command

369. pm.addIQProvider(\, \, new AdH

ocCommandDataProvider()); 370. // Chat State

371. ChatStateExtension.Provider chatState = new ChatStateExtension.Provider(); 372. pm.addExtensionProvider(\, \, cha

tState);

373. pm.addExtensionProvider(\, \,

374. chatState);

375. pm.addExtensionProvider(\, \, cha

tState);

376. pm.addExtensionProvider(\, \, c

hatState);

377. pm.addExtensionProvider(\, \, chatS

tate);

378. //MUC User,Admin,Owner

379. pm.addExtensionProvider(\, \, new MUCUse

rProvider());

380. pm.addIQProvider(\, \, new MUCAdmin

Provider());

381. pm.addIQProvider(\, \, new MUCOwner

Provider()); 382. } 383.

384. private static void initFeatures(XMPPConnection xmppConnection) { 385. ServiceDiscoveryManager.setIdentityName(\); 386. ServiceDiscoveryManager.setIdentityType(\);

387. ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(xmppConne

ction);

388. if(sdm == null) {

389. sdm = new ServiceDiscoveryManager(xmppConnection); 390. }

391. sdm.addFeature(\); 392. sdm.addFeature(\); 393. sdm.addFeature(\); 394. sdm.addFeature(\); 395. sdm.addFeature(\);

396. sdm.addFeature(\); 397. sdm.addFeature(\); 398. sdm.addFeature(\); 399. sdm.addFeature(\); 400. sdm.addFeature(\);

401. sdm.addFeature(\); 402. sdm.addFeature(\);

403. sdm.addFeature(\); 404. sdm.addFeature(\);

405. sdm.addFeature(\); 406. sdm.addFeature(\); 407. } 408. 409. }

上面有两张Spark客户端的聊天室列表占有者一列不同的原因:当使用以下代码获取时不能获取occupantsCount和subject的值:

view plain

1. System.out.println(roomInfo.getOccupantsCount() + \ + roomInfo.getSubject(

));

这是由于Openfire端有个bug(暂且这样说吧,我不知为什么Openfire这样做).首先修改Smack的一个bug,修改RoomInfo类的RoomInfo(DiscoverInfo info) 方法:

view plain

1. Iterator values = form.getField(\).getValues(); 2. if (values.hasNext()) {

3. this.subject = values.next(); 4. } 5. else {

6. this.subject = \;

7. }

改为:

view plain

1. final FormField subjField = form.getField(\); 2. this.subject = subjField == null ? \ : subjField.getValues().next();

修改Openfire的源码,org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl类的public DataForm getExtendedInfo(String name, String node, JID senderJID) 方法:

view plain

1. /*final FormField fieldOcc = dataForm.addField(); */ 2. fieldSubj.setVariable(\);

3. fieldSubj.setLabel(LocaleUtils.getLocalizedString(\

nts\));

4. fieldSubj.addValue(Integer.toString(room.getOccupantsCount())); 5.

改为:

view plain

1. final FormField fieldOccu= dataForm.addField(); 2. fieldOccu.setVariable(\);

3. fieldOccu.setLabel(LocaleUtils.getLocalizedString(\)); 4. fieldOccu.addValue(Integer.toString(room.getOccupantsCount()));

7. }

改为:

view plain

1. final FormField subjField = form.getField(\); 2. this.subject = subjField == null ? \ : subjField.getValues().next();

修改Openfire的源码,org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl类的public DataForm getExtendedInfo(String name, String node, JID senderJID) 方法:

view plain

1. /*final FormField fieldOcc = dataForm.addField(); */ 2. fieldSubj.setVariable(\);

3. fieldSubj.setLabel(LocaleUtils.getLocalizedString(\

nts\));

4. fieldSubj.addValue(Integer.toString(room.getOccupantsCount())); 5.

改为:

view plain

1. final FormField fieldOccu= dataForm.addField(); 2. fieldOccu.setVariable(\);

3. fieldOccu.setLabel(LocaleUtils.getLocalizedString(\)); 4. fieldOccu.addValue(Integer.toString(room.getOccupantsCount()));

本文来源:https://www.bwwdw.com/article/uu0p.html

Top