Apache mina 入門(四) —— 客戶端長連線方式實現斷線重連監聽
阿新 • • 發佈:2019-02-06
通過前面 Apache Mina 入門 (二)—— 非同步通訊機制
我們可以實現一個長連線的客戶端。但會發現一個問題,就是當網路、伺服器、應用程式出現問題而導致連線斷開後,我們的客戶端不能自動重連伺服器。導致客戶端程式癱瘓,不能使用。這個時候,通過增加一個監聽器,就能實現重連。
在我們實際生產環境中,斷線的原因可能更復雜:網路不穩定、延時、伺服器負載高、伺服器或者應用程式的傳送或者接收緩衝區滿等等問題都可能導致資料傳輸過程出現類似於斷線的情況,這個時候,光檢測Session關閉是遠遠不夠的,這個時候就需要一種重連機制,比如讀寫空閒超過30秒,就進行重連。對於資料不間斷、實時性高、資料量大的應用場景,更是實用。
具體實現程式碼如下:
/**
* 新增重連監聽
*
* @author liuc
* @date 2017-12-20
*
*/
public class ClientReconnectTest {
public static IoSession session = null;
public static NioSocketConnector connector = null;
public static void main(String[] args) {
connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(30000 ); // 設定連線超時
connector.getSessionConfig().setReceiveBufferSize(10240); // 設定接收緩衝區的大小
connector.getSessionConfig().setSendBufferSize(10240);// 設定輸出緩衝區的大小
connector.getFilterChain().addLast("logger", new LoggingFilter());
connector.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new ByteArrayCodecFactory()));// 設定編碼過濾器
connector.setHandler(new ClientHandler());// 設定事件處理器
connector.setDefaultRemoteAddress(new InetSocketAddress("127.0.0.1",
8888));// 設定預設訪問地址
// 新增重連監聽---實現自動重連
connector.addListener(new IoListener() {
@Override
public void sessionDestroyed(IoSession arg0) throws Exception {
//重連10次
for (int i= 0 ;i <= 10; i++) {
try {
Thread.sleep(3000);
ConnectFuture future = connector.connect();
future.awaitUninterruptibly();// 等待連線建立成功
session = future.getSession();// 獲取會話
if (session.isConnected()) {
System.out.println("斷線重連["
+ connector.getDefaultRemoteAddress()
.getHostName()
+ ":"
+ connector.getDefaultRemoteAddress()
.getPort() + "]成功");
break;
}
} catch (Exception ex) {
System.out.println("重連伺服器登入失敗,3秒再連線一次:" + ex.getMessage());
}
}
}
});
//確保連線成功,連線n次,
for (int i= 0 ;i <= 5; i++) {
try {
ConnectFuture future = connector.connect();
future.awaitUninterruptibly(); // 等待連線建立成功
session = future.getSession(); // 獲取會話
if(session.isConnected()){
System.out.println("連線服務端"
+ connector.getDefaultRemoteAddress()
.getHostName()
+ ":"
+ connector.getDefaultRemoteAddress()
.getPort()
+ "[成功]"
+ ",,時間:"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date()));
break;
}
} catch (RuntimeIoException e) {
System.out.println(
"連線服務端"
+ connector.getDefaultRemoteAddress()
.getHostName()
+ ":"
+ connector.getDefaultRemoteAddress()
.getPort()
+ "失敗"
+ ",,時間:"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date())
+ ", 連線SOCKET服務異常,請檢查SOCKET埠、IP是否正確,MSG服務是否啟動,異常內容:"
+ e.getMessage());
try {
Thread.sleep(5000);// 連線失敗後,重連間隔5s
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
BaseMessageForServer message = new BaseMessageForServer();
String content = "hello world!";
CRC32 crc = new CRC32();
try {
crc.update(content.getBytes("GBK"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
message.setFuncid(5);
message.setPacketIdCode(10000);
message.setContent(content);
message.setCheckCode(crc.getValue());
message.setLength(content.getBytes().length);
session.write(message);
}
}