資料參考來源自李海峰,並略作修改。
Apache_Mina_Server_2.0中文參考手冊V1.0 PDF版下載
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2012年資料/11月/24日/使用Mina模擬短信的收發/Apache_Mina_Server_2.0中文參考手冊V1.0 PDF版
This is Apache Mina 2.0.4, Let`s drink code....
下面是用於模擬短信協議內容的實體類
- package com.mina.model;
-
- /**
- * 模擬短信協議內容的對象
- * @see M sip:wap.fetion.com.cn SIP-C/2.0 //狀態行,一般表示協議的名字、版本號等
- * @see S: 1580101xxxx //短信的發送號碼
- * @see R: 1880202xxxx //短信的接收號碼
- * @see L: 21 //短信的字節數
- * @see 你好!!Hello World!! //短信的內容
- * @see 上面每行的末尾使用ASCII的10(\n)作為換行符
- */
- public class SmsObject {
- private String sender; //短信發送者
- private String receiver; //短信接收者
- private String message; //短信內容
- /*三個屬性的getter和setter略*/
- }
下面是Mina編寫的服務端主類MyServer.java
- package com.mina.server;
-
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.nio.charset.Charset;
-
- 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.transport.socket.nio.NioSocketAcceptor;
-
- import com.mina.factory.CmccSipcCodecFactory;
-
- public class MyServer {
- public static void main(String[] args) throws IOException {
- IoAcceptor acceptor = new NioSocketAcceptor();
- acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
- acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CmccSipcCodecFactory(Charset.forName("UTF-8"))));
- acceptor.setHandler(new ServerHandler());
- acceptor.bind(new InetSocketAddress(9876));
- System.out.println("Mina Server is Listing on := 9876");
- }
- }
下面是服務端的消息處理器ServerHandler.java
- package com.mina.server;
-
- import org.apache.mina.core.service.IoHandlerAdapter;
- import org.apache.mina.core.session.IoSession;
-
- import com.mina.model.SmsObject;
-
- public class ServerHandler extends IoHandlerAdapter {
- @Override
- public void messageReceived(IoSession session, Object message) throws Exception {
- SmsObject sms = (SmsObject)message;
- System.out.println("The message received from Client is [" + sms.getMessage() + "]");
- }
- @Override
- public void sessionOpened(IoSession session) throws Exception{
- System.out.println("InComing Client:" + session.getRemoteAddress());
- }
- }
下面是Mina編寫的客戶端主類MyClient.java
- package com.mina.client;
-
- import java.net.InetSocketAddress;
- import java.nio.charset.Charset;
-
- import org.apache.mina.core.service.IoConnector;
- import org.apache.mina.filter.codec.ProtocolCodecFilter;
- import org.apache.mina.transport.socket.nio.NioSocketConnector;
-
- import com.mina.factory.CmccSipcCodecFactory;
-
- public class MyClient {
- public static void main(String[] args) {
- IoConnector connector = new NioSocketConnector();
- connector.setConnectTimeoutMillis(3000);
- connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CmccSipcCodecFactory(Charset.forName("UTF-8"))));
- connector.setHandler(new ClientHandler());
- connector.connect(new InetSocketAddress("localhost", 9876));
- }
- }
下面是客戶端的消息處理器ClientHandler.java
- package com.mina.client;
-
- import org.apache.mina.core.service.IoHandlerAdapter;
- import org.apache.mina.core.session.IoSession;
-
- import com.mina.model.SmsObject;
-
- public class ClientHandler extends IoHandlerAdapter {
- @Override
- public void sessionOpened(IoSession session) throws Exception {
- SmsObject sms = new SmsObject();
- sms.setSender("15025302990");
- sms.setReceiver("13716700602");
- sms.setMessage("Hi Jadyer,這是我用Mina2.x發給你的消息....");
- session.write(sms);
- }
- }
下面是我們自定義的編解碼工廠類CmccSipcCodecFactory.java
- package com.mina.factory;
-
- import java.nio.charset.Charset;
-
- 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;
-
- import com.mina.codec.CmccSipcDecoder;
- import com.mina.codec.CmccSipcEncoder;
-
- /**
- * 自定義編解碼工廠
- * @see 實際上這個工廠類就是包裝了編碼器、解碼器
- * @see 通過接口中的getEncoder()、getDecoder()方法向ProtocolCodecFilter過濾器返回編解碼器實例
- * @see 以便在過濾器中對數據進行編解碼
- */
- public class CmccSipcCodecFactory implements ProtocolCodecFactory {
- private final CmccSipcEncoder encoder;
- private final CmccSipcDecoder decoder;
- public CmccSipcCodecFactory(){
- this(Charset.defaultCharset());
- }
- public CmccSipcCodecFactory(Charset charset){
- this.encoder = new CmccSipcEncoder(charset);
- this.decoder = new CmccSipcDecoder(charset);
- }
- @Override
- public ProtocolDecoder getDecoder(IoSession arg0) throws Exception {
- return decoder;
- }
- @Override
- public ProtocolEncoder getEncoder(IoSession arg0) throws Exception {
- return encoder;
- }
- }
重頭戲:下面是我們自定義的編碼器CmccSipcEncoder.java
- package com.mina.codec;
-
- 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;
-
- import com.mina.model.SmsObject;
-
- /**
- * 自定義編碼器
- * Mina中編寫編碼器可以實現ProtocolEncoder,其中有encode()、dispose()兩個方法需要實現
- * dispose()用於在銷毀編碼器時釋放關聯的資源,由於該方法一般我們並不關心,故通常直接繼承適配器ProtocolEncoderAdapter
- * @see ==============================================================================================================
- * @see 相比較解碼(字節轉為JAVA對象,也叫拆包)來說,編碼(Java對象轉為字節,也叫做打包)就很簡單了
- * @see 我們只需要把Java對象轉為指定格式的字節流,然後write()就可以了
- * @see ==============================================================================================================
- * @see 解碼器的編寫有以下幾個步驟
- * @see 1、將encode()方法中的message對象強制轉換為指定的對象類型
- * @see 2、創建IoBuffer緩沖區對象,並設置為自動擴展
- * @see 3、將轉換後的message對象中的各個部分按照指定的應用層協議進行組裝,並put()到IoBuffer緩沖區
- * @see 4、數據組裝完畢後,調用flip()方法,為輸出做好准備
- * @see 切記在write()方法之前調用IoBuffer的flip()方法,否則緩沖區的position的後面是沒有數據可以用來輸出的
- * @see 你必須調用flip()方法將position移至0,limit移至剛才的position。這個flip()方法的含義請參看java.nio.ByteBuffer
- * @see 5、最後調用ProtocolEncoderOutput的write()方法輸出IoBuffer緩沖區實例
- * @see ==============================================================================================================
- */
- public class CmccSipcEncoder extends ProtocolEncoderAdapter {
- private final Charset charset;
- public CmccSipcEncoder(Charset charset){
- this.charset = charset;
- }
-
- /**
- * 依據傳入的字符集類型對message對象進行編碼
- * 編碼的方式就是按照短信協議拼裝字符串到IoBuffer緩沖區,然後調用ProtocolEncoderOutput的write()方法輸出字節流
- */
- @Override
- public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
- SmsObject sms = (SmsObject)message;
- CharsetEncoder ce = charset.newEncoder();
- IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);
- String statusLine = "M sip:wap.fetion.com.cn SIP-C/2.0";
- String sender = sms.getSender();
- String receiver = sms.getReceiver();
- String smsContent = sms.getMessage();
- buffer.putString(statusLine+'\n', ce);
- buffer.putString("S: "+sender+'\n', ce);
- buffer.putString("R: "+receiver+'\n', ce);
- //使用String類與Byte[]類型之間的轉換方法獲得轉為字節流後的字節數
- buffer.putString("L: "+smsContent.getBytes(charset).length+'\n', ce);
- buffer.putString(smsContent, ce);
- buffer.flip();
- out.write(buffer);
- }
- }