在网络不稳定时,openfire容易出现掉包情况,原因是在客户端掉线时,openfire并不能马上知道客户端已经断线,至于要多久才能发现客户端断线,跟服务器端设置的Idle Connections 时间有关。默认为360秒。
为解决掉包问题,xmpp协议支持消息回执,这个只需在客户端发消息时设置要求回执就行,服务器端不需要另外设置。
使用smack设置消息回执方法
package com.penngo.test;
import java.awt.EventQueue;
public class ReceiptDialog extends JDialog {
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ReceiptDialog dialog = new ReceiptDialog();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the dialog.
*/
public ReceiptDialog() throws Exception{
setBounds(100, 100, 450, 300);
getContentPane().setLayout(null);
textField = new JTextField();
textField.setBounds(20, 20, 301, 22);
getContentPane().add(textField);
textField.setColumns(10);
Connection.DEBUG_ENABLED = true; // 打开smack debug
ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222);//52222
config.setSendPresence(true);
final Connection connection = new XMPPConnection(config);
// 如果对方的消息要求回执,自动回复回执。
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE, new DeliveryReceipt.Provider());
pm.addExtensionProvider(DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE, new DeliveryReceiptRequest.Provider());
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();
connection.connect();
String domain = connection.getServiceName();
// test1登录,发送消息给test2
// String from = "test1";
// final String to = "test2" + "@" + domain;
//test2登录,发送消息给test1
String from = "test2";
final String to = "test1" + "@" + domain;
connection.login(from, "123456", "pc");
// Presence p = new Presence(Presence.Type.available);
// p.setMode(Mode.chat);
// p.setStatus("在线");
// connection.sendPacket(p);
final Chat chat = connection.getChatManager().createChat(to, null);
JButton sendButton = new JButton("发送");
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Message message = new Message();
message.setFrom(connection.getUser());
message.setTo(to);
message.setBody(textField.getText());
DeliveryReceiptManager.addDeliveryReceiptRequest(message); // 回执设置,要求对方收到消息后提供回执
System.out.println("发送=======" + message.toXML());
try{
chat.sendMessage(message);
}
catch(Exception ex){
ex.printStackTrace();
}
}
});
sendButton.setBounds(331, 19, 93, 23);
getContentPane().add(sendButton);
}
}
运行结果,在smack debug window中查看数据
test2发送消息给test1,消息id为Winlh-55

test1发送回执给test2,告诉test2消息Winlh-55已经收到

原文:http://my.oschina.net/penngo/blog/339064