`
guizuhong2005
  • 浏览: 22029 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Smack使用简介

    博客分类:
  • xmpp
阅读更多

1 概述
    Smack是一个用于和XMPP服务器通信的类库,由此可以实现即时通讯和聊天。

1.1 主要优势
 简单易用,并且有十分强大的API,只需三行代码就可以向用户发关文本消息:
XMPPConnection connection = new XMPPConnection("jabber.org");
connection.login("mtucker", "password");
connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");

1)使用者不需要进行包级别的编码。
2)使用者不需熟悉XMPP XML格式。
3)提供了简单的设计以进行通讯,允许在每个消息中设置任意数量的属性,包括java对象。
4)Apache许可下的开源类库。
5)Smack的唯一必要条件是JDK 1.2 或更高版本。


2 smack主要流程

2.1 建立连接和登陆
    XMPPConnection类用来建立到XMPP服务器的连接,下面是建立连接的例子:
// 建立一个到jabber.org服务器的连接。
XMPPConnection conn1 = new XMPPConnection("jabber.org");
// 通过一个特殊的端口建立一个到jabber.org服务器的连接。
XMPPConnection conn2 = new XMPPConnection("jabber.org", 5222);
// 建立一个到jabber.org服务器的SSL连接。
XMPPConnection conn3= new SSLXMPPConnection("jabber.org");
// 使用用户名和密码登陆。
XMPPConnection.login(String username, String password)


2.2 操作Roster
    Roster可以用来跟踪其它用户的有效性。通过Roster类可以找到所有Roster登陆、他们所属的组以及每个登陆当前的存在状态。Roster通过XMPPConnection.getRoster()这个方法获得。

2.3 读写Packet
从客户端以XML格式发送到XMPP服务器的每个消息被称为一个“packet”。org.jivesoftware.smack.packet包中包含了一些类,这些类封装了XMPP所允许的三个不同的基本packet类型(message,presence和IQ)。
像Chat和GroupChat这样的类提供了更高类别的构造能够自动地创建和发送packet,但是我们也可以直接创建和发送packet。
// 创建一个新的presence. 传入false以指示我们已经无效了
Presence presence = new Presence(Presence.Type.UNAVAILABLE);
presence.setStatus("Gone fishing");
// 发送packet (假设已经有了一个名为"con"的XMPPConnection实例)
con.sendPacket(presence);

    Smack提供两种方法读取收到的packet:PacketListener[packet监听器]和PacketCollector[packet收集器]。二者都是使用PacketFilter实例来决定哪个packet应该被处理。packet监听器用于事件样式的编程,而packet收集器有一个可以做轮询和阻塞操作的packet的结果队列。所以,当我们想对一个有可能随时到来的packet采取一些操作时,使用packet监听器;而当我们想等待一个特别的packet到来时,使用packet收集器。

3 发送消息
   往复地发送消息处于即时通讯的核心地位。两个类辅助发送和接收消息:
    org.jivesoftware.smack.Chat,用于在两个人之间发送消息。
    org.jivesoftware.smack.GroupChat,用于加入聊天室在多个人之间发送消息。
    Chat和 GroupChat类都是使用org.jivesoftware.smack.packet.Message packet类来发送消息。

3.1 Chat
    一个chat在两个用户之间创建一个消息线程(通过线程ID)。下面这段代码演示了怎样和用户创建一个新的Chat并向他们发送一条文本消息:
// 假设我们已经创建了一个名为"connection"的XMPPConnection。
Chat newChat = connection.createChat("jsmith@jivesoftware.com");
newChat.sendMessage("Howdy!");

    Chat.sendMessage(String)方法可以方便地创建一个Message对象,用字符串参数设置消息正文或额外的值,然后发送消息。使用的是Chat.createMessage()和Chat.sendMessage(Message)方法,如下面代码片段所示:

// 假设我们已经创建了一个名为"connection"的XMPPConnection。
Chat newChat = connection.createChat("jsmith@jivesoftware.com");
Message newMessage = newChat.createMessage();
newMessage.setBody("Howdy!");
message.setProperty("favoriteColor", "red");
newChat.sendMessage(newMessage);


Chat对象能够让我们很容易监听其它聊天参与者的回复。下面这段代码演示的功能类似鹦鹉学舌--它将回复对方输入的一切消息。

// 假设我们已经创建了一个名为"connection"的XMPPConnection。
Chat newChat = connection.createChat("jsmith@jivesoftware.com");
newMessage.setBody("Hi, I'm an annoying parrot-bot! Type something back to me.");
while (true) {
    // 等待用户发送给我们的下一条消息。
    Message message = newChat.nextMessage();
    // 将对方发送过来的消息原样发送给他。
    newChat.sendMessage(message.getBody());
}


以上这段代码使用了这个Chat.nextMessage()方法得到下一条消息,它将等待不确定何时到来的另一条消息。当然也有其它的方法用于等待特定时间段到来的新消息,或者可以添加一个监听器,它将在每次有消息到来时通知用户。

3.2 GroupChat
通过GroupChat连接到服务器上的聊天室,在发送或接收消息之前,必须用一个昵称加入聊天室。下面这段代码演示了连接到一个聊天室并发送一条消息:
// 假设我们已经创建了一个名为"connection"的XMPPConnection。
GroupChat newGroupChat = connection.createGroupChat("test@jivesoftware.com");
// 用昵称"jsmith"加入这处群。
newGroupChat.join("jsmith");
// 向聊天室中的其它人发送一条消息。
newGroupChat.sendMessage("Howdy!");

    通常,在群中发送和接收消息和在Chat类中非常相似。

4 roster和presence
    roster可以跟踪其它用户的有效性(存在),通过使用像“朋友”和“同事”这样的组来组织用户。其它IM系统如朋友列表,联系列表引用roster。
一个roster实例通过XMPPConnection.getRoster()方法获得,但仅当成功登陆服务器之后才可用。
4.1 名薄登陆
在roster中每个用户用一个RosterEntry表示,它包括:
1)一个XMPP地址(例如 jsmith@example.com)。
2)一个分配给用户的名字(例如 "Joe")。
3)登陆所属的roster组列表。如果roster登陆不属于任何组,它将被称为“unfiled entry”。
下面的代码片段打印roster中的所有登陆:
Roster roster = con.getRoster();
for (Iterator i=roster.getEntries(); i.hasNext(); ){
    System.out.println(i.next());
}

也可能用方法获得单个登陆,未定义登陆列表,或者获得一个或所有roster组。

4.2 presence
roster中的每个登陆有presence与之关联。Roster.getPresence(String user)方法可以返回一个用户Presence的对象,如果用户不在线或我们没有预订用户的presence将会返回null。注意:一般而言,presence预订一般受用户是否在roster中的约束,但这并不适应所有情况。
一个用户可以有在线或离线两种presence。当用户在线时,他们的可能包含外延信息,如他们正在做什么,他们是否愿意被打扰等等。

4.3 监听roster和presence的变化
roster类的典型应用就是显示组的树型视图和含有当前presence值的登陆。
presence信息很可能经常变化,roster登陆也可能经常改变或被删除。为了监听roster和presence数据的变化,我们应该使用RosterListener。下面的代码片段注册了一个roster的RosterListener,它能够在标准输出中打印任何presence的变化。一个标准的客户端可以使用类似的代码用变化的信息来更新roster用户界面。
final Roster roster = con.getRoster();
roster.addRosterListener(new RosterListener() {
    public void rosterModified() {
        // 这个例子中忽略这个事件。
    }
    public void presenceChanged(String user) {
        // 如果presence无效,将会打印"null",
        System.out.println("Presence changed: " + roster.getPresence(user));
    }
});


4.4 向roster中添加登陆
roster和presence使用一种基于许可的模式,用户只有在被许可的情况下才能被添加到别人的roster中。这样可以保护用户的隐私因为只有经核准的其它用户才能查看他们的presence信息。因此,只有当其它用户接受我们的请求时才能添加新的roster登陆。Smack通过以下三种方式中的一种处理presence预订请求:
1)自动接受所有presence预订请求。
2)自动拒绝所有presence预订请求。
3)手动处理presence预订请求。
    通过Roster.setSubscriptionMode(int subscriptionMode)方法设置对请求的处理方式。简易客户端通常使用一种自动方式处理预订请求,而复杂客户端应该手动处理方式,请最终用户接受或拒绝请求。如果使用手动方式,应该注册一个PacketListener以监听Presence.Type.SUBSCRIBE类型的Presence packet。

5 接收消息
Smack提供灵活的框架来通过两种构造处理收到的packet:
1)org.jivesoftware.smack.PacketCollector —— 一同步等待新packet的类。
2)org.jivesoftware.smack.PacketListener —— 异步通知的packet的接口。
packet监听器用于事件样式的编程,而packet收集器有一个可以做轮询和阻塞操作的packet的结果队列。所以,当我们想对一个有可能随时到来的packet采取一些操作时,使用packet监听器;而当我们等待一个特别的packet到来时,使用packet收集器。
3)org.jivesoftware.smack.filter.PacketFilter 接口决定哪个特别的将会被传递到PacketCollector或PacketListener。   org.jivesoftware.smack.filter package包中有许多预定义的过滤器。

下面的代码片段演示注册了一个packet收集器和一个packet 监听器:
// 创建一个packet过滤器来监听来自一个特定用户的新的消息
//我们可以使用一个AndFilter来结合其它两个过滤器。
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class), 
        new FromContainsFilter("mary@jivesoftware.com"));
// 假设我们已经创建了一个名为"connection"的XMPPConnection。
// 首先,用我们创建的过滤器注册一个packet收集器。
PacketCollector myCollector = connection.createPacketCollector(filter);
// 接下来,创建一个packet监听器。我们可以简便地使用匿名内部类。
PacketListener myListener = new PacketListener() {
        public void processPacket(Packet packet) {
            // 在这里用收到的packet做些什么。
        }
    };
// 注册这个监听器。
connection.addPacketListener(myListener, filter);


5.1 标准Packet过滤器
Smack包括丰富的packet 过滤器集,当然我们可以通过实现PacketFilter接口创建自己的过滤器。默认的过滤器集包括:
 PacketTypeFilter ——特定类的packet过滤器。
 PacketIDFilter ——含有特定packet ID的packet过滤器。
 ThreadFilter ——含有特定线程ID的消息packet过滤器。
 ToContainsFilter ——发送到特定地址的packet过滤器。
 FromContainsFilter ——来自特定地址的packet过滤器。
 PacketExtensionFilter ——含有特定packet扩充的packet过滤器。AndFilter ——实现两个过滤器的逻辑“与”操作。
 OrFilter —— 实现两个过滤器的逻辑“或”操作。
 NotFilter ——实现一个过滤器的逻辑“非”操作。

6 Packet属性
Smack提供一个有效的机制,可以向packet附加任意属性。每个属性有一个String名字,这是一个java简单类型值(int, long, float, double, boolean)或者任何序列化对象(java对象可序列化当它实现了Serializable接口)。
6.1 使用API
所有主要对象支持属性,如Message对象。下面的代码显示如何设置属性:
Message message = chat.createMessage();
// 添加一个Color对象作为属性。
message.setProperty("favoriteColor", new Color(0, 0, 255));
// 添加一个int作为属性。
message.setProperty("favoriteNumber", 4);
chat.sendMessage(message);
使用如下代码获得这些属性:
Message message = chat.nextMessage();
// 获得一个Color对象属性。
Color favoriteColor = (Color)message.getProperty("favoriteColor");
// 获得一个intg属性,注意属性作为对象返回,我们必须把值转换为Integer,然后转换为int。
int favoriteNumber = ((Integer)message.getProperty("favoriteNumber")).intValue();


6.2 对象作为属性
使用对象作为属性值是一个非常强大和容易的交换数据的方式。
• Packet extension有更多标准方法添加额外数据到XMPP节。在某些情况下使用属性可能更方便,由于Smack自身会做处理XML的工作。
• 当你将Java对象作为属性发送时,只有运行着Java的客户端能够解释数据。所以,应该考虑将数据转换为一系列简单类型的值来代替Java对象。
• 作为属性值发送的对象必须实现Serialiable。另外,发送端和接收端都必须有同种的类,否则当系列化对象时会发生序列化异常。
• 序列化的对象可能会很大,这将使用更多的带宽和服务器资源。

6.3 XML格式
当前用于发送属性数据XML格式还不规范,所以很可能难以被不使用Smack的客户端识别。XML犹如下面所示:
<!--某块中的所有属性。 --> 
<properties xmlns="http://www.jivesoftware.com/xmlns/xmpp/properties">
    <!-- 首选,一个名为"prop1"的integer型值。--> 
    <property>
        <name>prop1</name>
        <value type="integer">123</value>
    <property>
    <!-- 其次,一个序列化的Java对象,然后从二进制数据转换到base-64编码的文本。 -->
    <property>
        <name>blah2</name>
        <value type="java-object">adf612fna9nab</value>
    <property>
</properties> 

当前支持的类型有:integer,long,float,double,boolean,string和java对象。

7 调试Smack
Smack包含两个内置的调试控制台,它可以跟踪客户端和服务器的XML通信量。smack.jar中的轻量型的调试器和smackx-debug.jar中的增强型的调试器。
调试模式可以通过两种方式激活:
1. 添加如下代码在创建新的连接之前:
XMPPConnection.DEBUG_ENABLED = true;
2. 设置Java系统属性smack.debugEnabled为true。这个系统属性可以在命令行设置:
java -Dsmack.debugEnabled=trueSomeApp
分享到:
评论
14 楼 oudewen 2017-12-08  
年轻人,这么基本的事情都知道就张口骂人,明显是smack版本问题,smack早期改版改动是挺大的。有问题在下面注明你用的版本接口改了不就行了?别人难得分享自己的经验,还要被你这种不懂事的菜鸟骂,有多冤啊。
金色阿泰 写道
我不骂你,我以理服人。
你看看楼主是怎么写的ok?
楼主是以下写法:
XMPPConnection connection = new XMPPConnection("jabber.org"); 
connection.login("mtucker", "password"); 
connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");
我最开始回复的是
XMPPConnection根本就没有createChat这个方法
而你用的是ChatManager 的createChat。
你写的跟楼主写的根本不一样,麻烦你认真点,OK?
你回复我的根本就是驴脣不对马嘴。

jyoeiei 写道
过了这么久发现你回了,那我也发一下我写的,安卓机和电脑上spark测试发收消息正常。如果你的代码也是OK的,那说明有多个实现方法。所以请不要随便喷人,留点口德。
private void sendMessage(){
// Assume we've created an XMPPConnection name "connection".
XMPPConnection connection = XwwConnectionManager.getInstance().getXmppConnectionAdapter().getXMPPConnection();
ChatManager chatmanager = connection.getChatManager();
String sendToUserId = "test03@192.168.0.251";
Chat newChat = chatmanager.createChat(sendToUserId, new MessageListener() {
    public void processMessage(Chat chat, Message message) {
        System.out.println("Received message: " + message);
    }
});

try {
String sendMessageStr = txtMessage.getText().toString();
    newChat.sendMessage(sendMessageStr);
}
catch (XMPPException e) {
    System.out.println("Error Delivering block");
}
catch (Exception e) {
    System.out.println("ChatManager SendMessage Exception");
}
}

金色阿泰 写道
jyoeiei 写道
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。

你怎么知道我没调查呢,你说我说的不对,说明你也是垃圾,因为你根本不会smack,没有真凭实据我是不会鉴定别人是垃圾的,告诉你正确答案,凭我多年对openfire的研究,你最好谦虚点。
//发送者登录
connection.login("admin", "1","web端登录");
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();

//获取域名
String serviceName=config.getServiceName();
//第一种发送消息方式
Message newmsg = new Message();
//接受者@jid
    newmsg.setTo("caoopenffuucckk"+"@"+serviceName);
    newmsg.setSubject("你好");
    newmsg.setBody(" 您好 您好 您好 今天48度");

    // 回执设置,要求对方收到消息后提供回执
    DeliveryReceiptManager.addDeliveryReceiptRequest(newmsg);
    // newmsg.setType(Message.Type.headline);则不支持离线
    // normal支持离线
    newmsg.setType(Message.Type.normal);
    connection.sendPacket(newmsg);

13 楼 金色阿泰 2017-03-01  
我不骂你,我以理服人。
你看看楼主是怎么写的ok?
楼主是以下写法:
XMPPConnection connection = new XMPPConnection("jabber.org"); 
connection.login("mtucker", "password"); 
connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");
我最开始回复的是
XMPPConnection根本就没有createChat这个方法
而你用的是ChatManager 的createChat。
你写的跟楼主写的根本不一样,麻烦你认真点,OK?
你回复我的根本就是驴脣不对马嘴。

jyoeiei 写道
过了这么久发现你回了,那我也发一下我写的,安卓机和电脑上spark测试发收消息正常。如果你的代码也是OK的,那说明有多个实现方法。所以请不要随便喷人,留点口德。
private void sendMessage(){
// Assume we've created an XMPPConnection name "connection".
XMPPConnection connection = XwwConnectionManager.getInstance().getXmppConnectionAdapter().getXMPPConnection();
ChatManager chatmanager = connection.getChatManager();
String sendToUserId = "test03@192.168.0.251";
Chat newChat = chatmanager.createChat(sendToUserId, new MessageListener() {
    public void processMessage(Chat chat, Message message) {
        System.out.println("Received message: " + message);
    }
});

try {
String sendMessageStr = txtMessage.getText().toString();
    newChat.sendMessage(sendMessageStr);
}
catch (XMPPException e) {
    System.out.println("Error Delivering block");
}
catch (Exception e) {
    System.out.println("ChatManager SendMessage Exception");
}
}

金色阿泰 写道
jyoeiei 写道
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。

你怎么知道我没调查呢,你说我说的不对,说明你也是垃圾,因为你根本不会smack,没有真凭实据我是不会鉴定别人是垃圾的,告诉你正确答案,凭我多年对openfire的研究,你最好谦虚点。
//发送者登录
connection.login("admin", "1","web端登录");
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();

//获取域名
String serviceName=config.getServiceName();
//第一种发送消息方式
Message newmsg = new Message();
//接受者@jid
    newmsg.setTo("caoopenffuucckk"+"@"+serviceName);
    newmsg.setSubject("你好");
    newmsg.setBody(" 您好 您好 您好 今天48度");

    // 回执设置,要求对方收到消息后提供回执
    DeliveryReceiptManager.addDeliveryReceiptRequest(newmsg);
    // newmsg.setType(Message.Type.headline);则不支持离线
    // normal支持离线
    newmsg.setType(Message.Type.normal);
    connection.sendPacket(newmsg);
12 楼 jyoeiei 2016-11-15  
过了这么久发现你回了,那我也发一下我写的,安卓机和电脑上spark测试发收消息正常。如果你的代码也是OK的,那说明有多个实现方法。所以请不要随便喷人,留点口德。
private void sendMessage(){
// Assume we've created an XMPPConnection name "connection".
XMPPConnection connection = XwwConnectionManager.getInstance().getXmppConnectionAdapter().getXMPPConnection();
ChatManager chatmanager = connection.getChatManager();
String sendToUserId = "test03@192.168.0.251";
Chat newChat = chatmanager.createChat(sendToUserId, new MessageListener() {
    public void processMessage(Chat chat, Message message) {
        System.out.println("Received message: " + message);
    }
});

try {
String sendMessageStr = txtMessage.getText().toString();
    newChat.sendMessage(sendMessageStr);
}
catch (XMPPException e) {
    System.out.println("Error Delivering block");
}
catch (Exception e) {
    System.out.println("ChatManager SendMessage Exception");
}
}

金色阿泰 写道
jyoeiei 写道
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。

你怎么知道我没调查呢,你说我说的不对,说明你也是垃圾,因为你根本不会smack,没有真凭实据我是不会鉴定别人是垃圾的,告诉你正确答案,凭我多年对openfire的研究,你最好谦虚点。
//发送者登录
connection.login("admin", "1","web端登录");
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();

//获取域名
String serviceName=config.getServiceName();
//第一种发送消息方式
Message newmsg = new Message();
//接受者@jid
    newmsg.setTo("caoopenffuucckk"+"@"+serviceName);
    newmsg.setSubject("你好");
    newmsg.setBody(" 您好 您好 您好 今天48度");

    // 回执设置,要求对方收到消息后提供回执
    DeliveryReceiptManager.addDeliveryReceiptRequest(newmsg);
    // newmsg.setType(Message.Type.headline);则不支持离线
    // normal支持离线
    newmsg.setType(Message.Type.normal);
    connection.sendPacket(newmsg);
11 楼 金色阿泰 2016-09-22  
jyoeiei 写道
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。


你倒是说啊,我的代码哪里不对,你说不出来我便经常骂你。奉劝你一句别那么自信。
10 楼 金色阿泰 2016-09-22  
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

我已经指出错误了,看你这回有什么话说。
9 楼 金色阿泰 2016-07-18  
jyoeiei 写道
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。


你不是说我误导别人吗?请指出我代码里的错误,指责不出来我天天骂你。
8 楼 金色阿泰 2016-07-16  
jyoeiei 写道
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。

你怎么知道我没调查呢,你说我说的不对,说明你也是垃圾,因为你根本不会smack,没有真凭实据我是不会鉴定别人是垃圾的,告诉你正确答案,凭我多年对openfire的研究,你最好谦虚点。
//发送者登录
connection.login("admin", "1","web端登录");
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();

//获取域名
String serviceName=config.getServiceName();
//第一种发送消息方式
Message newmsg = new Message();
//接受者@jid
    newmsg.setTo("caoopenffuucckk"+"@"+serviceName);
    newmsg.setSubject("你好");
    newmsg.setBody(" 您好 您好 您好 今天48度");

    // 回执设置,要求对方收到消息后提供回执
    DeliveryReceiptManager.addDeliveryReceiptRequest(newmsg);
    // newmsg.setType(Message.Type.headline);则不支持离线
    // normal支持离线
    newmsg.setType(Message.Type.normal);
    connection.sendPacket(newmsg);
7 楼 jyoeiei 2016-06-01  
哎,据我所知是你在误导别人,不要随便辱骂别人。PS在指责别人的时候,你有没有认真调查?(为了回复你,还特意注册了)
金色阿泰 写道
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。

6 楼 金色阿泰 2016-05-26  
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

楼主没发现的错误我发现了你还说我是垃圾,有本事你自己指出来错误啊。操!
5 楼 金色阿泰 2016-03-13  
hantaoai 写道
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊

他误导别人还不让骂吗?骂他只影响他一个人,他误导别人影响一大群人。
4 楼 xiaowu_005 2016-02-24  
楼主确实写的不对,GroupChat类根本没有
3 楼 hantaoai 2016-01-20  
金色阿泰 写道
楼主傻逼 XMPPConnection根本就没有createChat这个方法,还TMD写成connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!");完全是误导别人,傻逼楼主,艸泥妈的

特讨厌这种垃圾,张嘴就喷粪,如果人家错了你指出就行了,干嘛喷粪,你NB,自己写个啊
2 楼 yyp5257 2015-05-16  
Client 端api写的很全,感谢。server端有没有相关文章呢,希望帮助提供下
1 楼 l564203965 2015-03-31  
GroupChat 找不到这个类怎么办啊

相关推荐

Global site tag (gtag.js) - Google Analytics