Java - Apache Mina 自定義協議通訊
一、定義協議實體
import java.nio.charset.Charset;
/**
* 自定義協議的訊息體
*/
public class MyMsg {
/**
* 訊息長度
*/
private Integer lenth;
/**
* 傳送人
*/
private Long sender;
/**
* 接收人
*/
private Long receiver;
/**
* 訊息內容
*/
private String content;
public MyMsg() {
}
public Long getSender() {
return sender;
}
public void setSender(Long sender) {
this.sender = sender;
}
public Long getReceiver() {
return receiver;
}
public void setReceiver(Long receiver) {
this.receiver = receiver;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
/**
* 先計算長度,再返回。這裡長度包含長度本身的位元組
*/
public Integer getLenth() {
this.lenth = 4 + 8*2 + this.content.getBytes(Charset.forName("utf-8")).length;
return lenth;
}
public MyMsg(Long sender, Long receiver, String content) {
this.sender = sender;
this.receiver = receiver;
this.content = content;
}
@Override
public String toString() {
return "MyMsg [lenth=" + this.getLenth() + ", sender=" + sender + ", receiver="
+ receiver + ", content=" + content + "]";
}
}
二、定義編解碼器
1、編碼器
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
/**
* 編碼器
*/
public class MyEncoder extends ProtocolEncoderAdapter {
@Override
public void encode(IoSession session, Object message, ProtocolEncoderOutput encoderOutput)
throws Exception {
CharsetEncoder ce = Charset.forName("utf-8").newEncoder();
MyMsg msg = (MyMsg) message;
// Mina IoBuffer
IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);
buffer.putInt(msg.getLenth());
buffer.putLong(msg.getSender());
buffer.putLong(msg.getReceiver());
// 有多個可變長度的屬性時,可約定通過定義可變屬性的最大長度(多餘擷取不足補齊)或put之前put其長度等方式處理
buffer.putString(msg.getContent(), ce);
buffer.flip();
encoderOutput.write(buffer);
}
}
2、解碼器
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
/**
* 解碼器可繼承ProtocolEncoderAdapter,但它不利於處理粘包的情況
*/
public class MyDecoder extends CumulativeProtocolDecoder {
@Override
protected boolean doDecode(IoSession session, IoBuffer buffer, ProtocolDecoderOutput decoderOutput)
throws Exception {
CharsetDecoder de = Charset.forName("utf-8").newDecoder();
/**
* 這裡,如果長度不夠20位元組,就認為這條訊息還沒有累積完成
*/
if(buffer.remaining() < 20){
/**
* 停止呼叫decode,但如果還有資料沒有讀取完,將含有剩餘資料的IoBuffer儲存到IoSession中,
* 當有新資料包來的時候再和新的合併後再呼叫decoder解碼
* 注意:沒有消費任何資料時不能返回true,否則會丟擲異常
*/
return false;
}else{
int length = buffer.getInt();
MyMsg msg = new MyMsg();
msg.setSender(buffer.getLong());
msg.setReceiver(buffer.getLong());
// 注意:20 = 訊息長度的位元組 + 傳送人和接收人的位元組
msg.setContent(buffer.getString(length - 20, de));
decoderOutput.write(msg);
/**
* CumulativeProtocolDecoder會再次呼叫decoder,並把剩餘的資料發下來繼續解碼
*/
return true;
}
}
}
3、編解碼工廠
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
/**
* 編解碼工廠
*/
public class MyCoderFactory implements ProtocolCodecFactory{
private MyDecoder decoder;
private MyEncoder encoder;
public MyCoderFactory() {
this.decoder = new MyDecoder();
this.encoder = new MyEncoder();
}
@Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}
@Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
}
三、伺服器端
1、執行類
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class ServerMain {
public static void main(String[] args) throws IOException {
// 在伺服器端建立一個監聽連線的接收器 基於tcp/ip
IoAcceptor acceptor = new NioSocketAcceptor();
// 繫結的埠
SocketAddress address = new InetSocketAddress("localhost", 8888);
// 獲取過濾器鏈
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
// 新增日誌過濾器
chain.addLast("logger", new LoggingFilter());
// 配置自定義的編解碼器
chain.addLast("mycodec", new ProtocolCodecFilter(new MyCoderFactory()));
// 新增資料處理的處理器
acceptor.setHandler(new ServerHandler());
// 進行配置資訊的設定
acceptor.getSessionConfig().setReadBufferSize(100);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
// 繫結伺服器埠
acceptor.bind(address);
System.out.println("伺服器開始在 8888 埠監聽.......");
}
}
2、Handler
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
public class ServerHandler extends IoHandlerAdapter{
/**
* 接受訊息
*/
public void messageReceived(IoSession session, Object message)
throws Exception {
MyMsg msg = (MyMsg) message;
System.out.println("伺服器端接收到的訊息:" + msg);
// 返回一個訊息給客戶端
msg = new MyMsg(10000L, 10001L, "你好,這是來自伺服器的應答!");
session.write(msg);
}
/**
* 傳送訊息
*/
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("伺服器端開始傳送訊息...");
super.messageSent(session, message);
}
/**
* 會話開啟
*/
public void sessionOpened(IoSession session) throws Exception {
System.out.println("服務端會話已開啟...");
super.sessionOpened(session);
}
/**
* 異常處理
*/
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
System.out.println("服務端發生異常了...");
cause.printStackTrace();
}
/**
* 會話關閉
*/
public void sessionClosed(IoSession session) throws Exception {
System.out.println("服務端會話已關閉...");
super.sessionClosed(session);
}
/**
* 會話建立
*/
public void sessionCreated(IoSession session) throws Exception {
System.out.println("服務端會話已建立...");
super.sessionCreated(session);
}
/**
* 連線空閒
*/
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
System.out.println("服務端連線空閒中...");
super.sessionIdle(session, status);
}
}
四、客戶端
1、連線類
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class ClientMain {
public static void main(String[] args) {
// 建立客戶端聯結器 基於tcp/ip
NioSocketConnector connector = new NioSocketConnector();
// 連線的地址和埠
SocketAddress address = new InetSocketAddress("localhost",8888);
// 獲取過濾器鏈
DefaultIoFilterChainBuilder chain = connector.getFilterChain();
// 配置日誌過濾器和自定義編解碼器
chain.addLast("logger", new LoggingFilter());
chain.addLast("mycodec",new ProtocolCodecFilter(new MyCoderFactory()));
// 新增處理器
connector.setHandler(new ClientHandler());
// 連線到伺服器
ConnectFuture future = connector.connect(address);
// 等待連線建立完成
future.awaitUninterruptibly();
// 會話建立後傳送訊息到伺服器
MyMsg msg = new MyMsg(10001L, 10000L, "你好,這是來自客戶端的請求!");
future.getSession().write(msg);
// 等待28000毫秒後連線斷開
future.getSession().getCloseFuture().awaitUninterruptibly(28000);
// 關閉連線
connector.dispose();
}
}
2、Handler
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class ClientHandler extends IoHandlerAdapter{
/**
* 接收訊息
*/
public void messageReceived(IoSession session, Object message)
throws Exception {
System.out.println("客戶端接收到的訊息:" + (MyMsg)message);
}
/**
* 傳送訊息
*/
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("客戶端傳送訊息...");
super.messageSent(session, message);
}
/**
* 會話建立
*/
public void sessionOpened(IoSession session) throws Exception {
System.out.println("客戶端已經連線到了伺服器...");
}
/**
* 會話關閉
*/
public void sessionClosed(IoSession session) throws Exception {
System.out.println("連線關閉...");
super.sessionClosed(session);
}
}
五、結果
1、伺服器端
2、客戶端
六、資源
http://download.csdn.net/detail/u013379717/7574675
相關文章
- 如何利用 Netty 實現自定義協議通訊?Netty協議
- 如何動手實現一個自定義的通訊協議?協議
- 基於Netty實現自定義訊息通訊協議(協議設計及解析應用實戰)Netty協議
- 通訊協議協議
- Redis 通訊協議Redis協議
- HTTP通訊協議HTTP協議
- Mysql通訊協議MySql協議
- MQ通訊協議MQ協議
- web通訊協議Web協議
- netty自定義Decoder用於自定義協議Netty協議
- 網路通訊協議協議
- Dubbo-通訊協議協議
- 串列埠通訊協議串列埠協議
- Java - Apache Mina 簡單示例JavaApache
- 網路通訊協議-ICMP協議詳解!協議
- 網路通訊協議-TCP協議詳解!協議TCP
- 網路通訊協議-HTTP協議詳解!協議HTTP
- 網路通訊協議-SMTP協議詳解!協議
- 輕量通訊協議 --- MQTT協議MQQT
- HTTP協議的通訊框架HTTP協議框架
- WLAN常用的通訊協議協議
- 通訊協議:HTTP、TCP、UDP協議HTTPTCPUDP
- 15. SPI通訊協議協議
- IIC通訊協議筆記協議筆記
- SPI通訊協議筆記協議筆記
- 使用mina解析http協議的使用HTTP協議
- 元件間通訊--自定義事件元件事件
- mina 框架java服務端的搭建和通訊。框架Java服務端
- 倍福ADS協議通訊協議
- 通訊協議之序列化協議
- 快速理解網路通訊協議協議
- 工業通訊協議(一)- CAN協議
- 通訊協議和網路協議有什麼區別協議
- 詳解通訊資料協議ProtoBuf協議
- 物聯網通訊協議介紹協議
- 陌陌通訊協議的學習協議
- 485通訊協議問題淺析協議
- 簡易遊戲通訊協議框架1.0遊戲協議框架