使用Mina模拟短信的收发
使用Mina模拟短信的收发
资料参考来源自李海峰,并略作修改。
Apache_Mina_Server_2.0中文参考手册V1.0 PDF版下载
免费下载地址在 http://linux.bkjia.com/
用户名与密码都是www.bkjia.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);
- }
- }
|
评论暂时关闭