Quellcode durchsuchen

init 20220716 重构了sgip协议代码,发短信测试成功

lifuquan vor 2 Jahren
Ursprung
Commit
ec1a05febd
38 geänderte Dateien mit 2691 neuen und 3 gelöschten Zeilen
  1. 2 1
      .gitignore
  2. 20 1
      pom.xml
  3. 20 0
      src/main/java/com/nokia/sms/action/DeliverAction.java
  4. 21 0
      src/main/java/com/nokia/sms/action/ReportAction.java
  5. 14 0
      src/main/java/com/nokia/sms/pojo/Sms.java
  6. 45 0
      src/main/java/com/nokia/sms/service/SmsService.java
  7. 50 0
      src/main/java/com/nokia/sms/sgip/RespCaller.java
  8. 41 0
      src/main/java/com/nokia/sms/sgip/SgipConfig.java
  9. 149 0
      src/main/java/com/nokia/sms/sgip/codec/MessageUtil.java
  10. 26 0
      src/main/java/com/nokia/sms/sgip/codec/SgipCodecFactory.java
  11. 97 0
      src/main/java/com/nokia/sms/sgip/codec/SgipMessageDecoder.java
  12. 18 0
      src/main/java/com/nokia/sms/sgip/codec/SgipMessageEncoder.java
  13. 20 0
      src/main/java/com/nokia/sms/sgip/exception/ReadErrorException.java
  14. 201 0
      src/main/java/com/nokia/sms/sgip/filter/SGIPLoggingFilter.java
  15. 100 0
      src/main/java/com/nokia/sms/sgip/message/BindMessage.java
  16. 57 0
      src/main/java/com/nokia/sms/sgip/message/BindResponseMessage.java
  17. 174 0
      src/main/java/com/nokia/sms/sgip/message/DeliverMessage.java
  18. 57 0
      src/main/java/com/nokia/sms/sgip/message/DeliverResponseMessage.java
  19. 75 0
      src/main/java/com/nokia/sms/sgip/message/Head.java
  20. 110 0
      src/main/java/com/nokia/sms/sgip/message/ReportMessage.java
  21. 57 0
      src/main/java/com/nokia/sms/sgip/message/ReportResponseMessage.java
  22. 33 0
      src/main/java/com/nokia/sms/sgip/message/SendResult.java
  23. 28 0
      src/main/java/com/nokia/sms/sgip/message/SgipMessage.java
  24. 334 0
      src/main/java/com/nokia/sms/sgip/message/SubmitMessage.java
  25. 57 0
      src/main/java/com/nokia/sms/sgip/message/SubmitResponseMessage.java
  26. 26 0
      src/main/java/com/nokia/sms/sgip/message/UnBindMessage.java
  27. 26 0
      src/main/java/com/nokia/sms/sgip/message/UnBindResponseMessage.java
  28. 27 0
      src/main/java/com/nokia/sms/sgip/message/UnknowMessage.java
  29. 7 0
      src/main/java/com/nokia/sms/sgip/mo/server/Action.java
  30. 23 0
      src/main/java/com/nokia/sms/sgip/mo/server/BindChecker.java
  31. 84 0
      src/main/java/com/nokia/sms/sgip/mo/server/MOServer.java
  32. 141 0
      src/main/java/com/nokia/sms/sgip/mo/server/MOServerHandler.java
  33. 358 0
      src/main/java/com/nokia/sms/sgip/mt/client/MTClient.java
  34. 64 0
      src/main/java/com/nokia/sms/sgip/mt/client/MTClientHandler.java
  35. 35 0
      src/main/java/com/nokia/sms/sgip/servlet/MOServerServlet.java
  36. 72 0
      src/main/resources/sgipConfig.properties
  37. 19 0
      src/test/com/nokia/sms/service/SmsServiceTest.java
  38. 3 1
      短信网关接口说明.md

+ 2 - 1
.gitignore

@@ -1,2 +1,3 @@
 target/
-.vscode/
+.vscode/
+logs/

+ 20 - 1
pom.xml

@@ -2,7 +2,7 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-    <groupId>com.nokia</groupId>
+    <groupId>com.nokia.sms</groupId>
     <artifactId>sgip_sms_server</artifactId>
     <version>1.0</version>
 
@@ -18,6 +18,15 @@
     </properties>
 
     <dependencies>
+        <!-- mina把底层传输的字节码转换为Java对象,提供给应用程序;或者把应用程序返回的结果转换为字节码,交给底层传输 -->
+        <dependency>
+            <groupId>org.apache.mina</groupId>
+            <artifactId>mina-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.postgresql</groupId>
             <artifactId>postgresql</artifactId>
@@ -39,6 +48,16 @@
     </dependencies>
     <build>
         <finalName>sms_server</finalName>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <targetPath></targetPath>
+                <includes>
+                    <include>**/*.*</include>
+                </includes>
+            </resource>
+        </resources>
+        <testSourceDirectory>src/test</testSourceDirectory>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>

+ 20 - 0
src/main/java/com/nokia/sms/action/DeliverAction.java

@@ -0,0 +1,20 @@
+package com.nokia.sms.action;
+
+import com.nokia.sms.sgip.message.DeliverMessage;
+import com.nokia.sms.sgip.message.SgipMessage;
+import com.nokia.sms.sgip.mo.server.Action;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class DeliverAction implements Action {
+
+	public void execute(SgipMessage message) {
+		if (message instanceof DeliverMessage) {
+			// 如果是上行消息则做相应的处理,如入库等等
+			DeliverMessage dMessage = (DeliverMessage) message;
+			log.info("收到上行消息。内容为:" + dMessage.getMessageContent());
+		}
+	}
+
+}

+ 21 - 0
src/main/java/com/nokia/sms/action/ReportAction.java

@@ -0,0 +1,21 @@
+package com.nokia.sms.action;
+
+import com.nokia.sms.sgip.message.ReportMessage;
+import com.nokia.sms.sgip.message.SgipMessage;
+import com.nokia.sms.sgip.mo.server.Action;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ReportAction implements Action {
+
+	public void execute(SgipMessage message) {
+		if (message instanceof ReportMessage) {
+			// 收到状态报告
+			ReportMessage rMessage = (ReportMessage) message;
+			log.info("收到Report." + rMessage.toString());
+		}
+
+	}
+
+}

+ 14 - 0
src/main/java/com/nokia/sms/pojo/Sms.java

@@ -0,0 +1,14 @@
+package com.nokia.sms.pojo;
+
+import lombok.Data;
+
+@Data
+public class Sms {
+
+    private String id;
+    private String fromSystem;
+    private String phone;
+    private String message;
+    private String messageType;
+    private String internalId;
+}

+ 45 - 0
src/main/java/com/nokia/sms/service/SmsService.java

@@ -0,0 +1,45 @@
+package com.nokia.sms.service;
+
+import java.util.Arrays;
+
+import org.springframework.stereotype.Service;
+
+import com.nokia.sms.pojo.Sms;
+import com.nokia.sms.sgip.message.SendResult;
+import com.nokia.sms.sgip.mo.server.MOServer;
+import com.nokia.sms.sgip.mt.client.MTClient;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+public class SmsService {
+
+    public boolean sendMessage(Sms sms) {
+        log.debug("准备发送短信: {}", sms);
+        // 获取单例的MO服务端 必须在应用启动的时候就调用,用于启动上行和报告消息的监听端口,需要调用一次就行了
+        // 不调用该代码,会导致无法接受上行和报告短信
+        MOServer server = MOServer.getInstance();
+
+        // 获取单例的MTClient
+        MTClient client = MTClient.getInstance();
+
+        // 发送短信
+        SendResult[] results = client.sendMessage("8613231899751", "这是一条测试短信");
+        for (SendResult sendResult : results) {
+            log.debug("短信已成功发送, 短信序号为: {} , 发送结果: {}", Arrays.toString(sendResult.getFlowId()), sendResult.getResult());
+        }
+
+        try {
+            // 网关的报告消息需要一定时间才发送到,sleep一下等待报告消息
+            Thread.sleep(10000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        // 销毁应用
+        server.dispose();
+        client.dispose();
+        return true;
+    }
+}

+ 50 - 0
src/main/java/com/nokia/sms/sgip/RespCaller.java

@@ -0,0 +1,50 @@
+package com.nokia.sms.sgip;
+
+import java.util.concurrent.Callable;
+
+import com.nokia.sms.sgip.message.Head;
+import com.nokia.sms.sgip.message.SgipMessage;
+import com.nokia.sms.sgip.message.BindResponseMessage;
+import com.nokia.sms.sgip.message.SubmitResponseMessage;
+import com.nokia.sms.sgip.message.DeliverResponseMessage;
+import com.nokia.sms.sgip.message.ReportResponseMessage;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class RespCaller implements Callable<Byte> {
+
+    private SgipMessage respMessage;
+
+    @Override
+    public Byte call() throws Exception {
+        byte result = -99;
+        Head head = this.respMessage.getHead();
+        switch (head.getCommandId()) {
+            case -2147483647:
+                result = ((BindResponseMessage) this.respMessage).getOperateResult();
+                break;
+            case -2147483645:
+                result = ((SubmitResponseMessage) this.respMessage).getOperateResult();
+                break;
+            case -2147483644:
+                result = ((DeliverResponseMessage) this.respMessage).getOperateResult();
+                break;
+            case -2147483643:
+                result = ((ReportResponseMessage) this.respMessage).getOperateResult();
+                break;
+            case -2147483646:
+                result = -100;
+                break;
+            default:
+                result = -100;
+        }
+        log.trace("result=" + result);
+        return Byte.valueOf(result);
+    }
+
+    public void setRespMessage(SgipMessage message) {
+        this.respMessage = message;
+    }
+    
+}

+ 41 - 0
src/main/java/com/nokia/sms/sgip/SgipConfig.java

@@ -0,0 +1,41 @@
+package com.nokia.sms.sgip;
+
+import java.net.URLDecoder;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SgipConfig {
+    private static CompositeConfiguration config;
+    private static String configFile = "sgipConfig.properties";
+
+    public static void setConfigFile(String configFile) {
+        SgipConfig.configFile = configFile;
+    }
+
+    public static synchronized CompositeConfiguration getConfig() {
+        if (config == null) {
+            try {
+                config = new CompositeConfiguration();
+                if (configFile == null) {
+                    configFile = SgipConfig.class.getResource("/sgipConfig.properties").getFile();
+                }
+                configFile = URLDecoder.decode(configFile, "utf-8");
+                PropertiesConfiguration propsConfig = new PropertiesConfiguration();
+                propsConfig.setEncoding("UTF-8");
+                propsConfig.load(configFile);
+                FileChangedReloadingStrategy propsReload = new FileChangedReloadingStrategy();
+                propsReload.setRefreshDelay(60000L);
+                propsConfig.setReloadingStrategy(propsReload);
+                config.addConfiguration(propsConfig);
+            } catch (Exception ex) {
+                log.error("", ex);
+            }
+        }
+        return config;
+    }
+}

+ 149 - 0
src/main/java/com/nokia/sms/sgip/codec/MessageUtil.java

@@ -0,0 +1,149 @@
+package com.nokia.sms.sgip.codec;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+public class MessageUtil {
+    private static int sgipSeq;
+    private static final SimpleDateFormat dateForamt = new SimpleDateFormat("MMddHHmmss");
+    public static final Charset gbkCharset = Charset.forName("GBK");
+    public static final CharsetDecoder gbkDecoder = gbkCharset.newDecoder();
+    public static final CharsetEncoder gdkEncoder = gbkCharset.newEncoder();
+    public static final Charset ucs2Charset = Charset.forName("UnicodeBigUnmarked");
+    public static final CharsetDecoder ucs2Decoder = ucs2Charset.newDecoder();
+    public static final CharsetEncoder ucs2Encoder = ucs2Charset.newEncoder();
+    public static final byte[] IE_PORT_APP = { 5, 4, 11, -124, 35, -16 };
+    public static final byte[] WBXML_HEADER = { 41, 6, 6, 3, -82, -127, -22, -115, -54, 2, 5, 106, 0, 69, -58, 8, 12,
+            3 };
+    public static final byte[] END1 = { 0, 1, 3 };
+    public static final byte[] END2 = { 0, 1, 1 };
+    private static int nodeId;
+    private static byte smsSeq = 0;
+
+    public static void setNodeId(int nodeId) {
+        MessageUtil.nodeId = nodeId;
+    }
+
+    public static int[] getFlowId() {
+        int[] flowId = new int[3];
+        flowId[0] = nodeId;
+        flowId[1] = Integer.parseInt(dateForamt.format(new Date()));
+        flowId[2] = sgipSeq;
+        if (sgipSeq == 2147483647) {
+            sgipSeq = 0;
+        } else {
+            sgipSeq += 1;
+        }
+        return flowId;
+    }
+
+    public static byte[] getBytes(String str, int len) {
+        byte[] bytes = null;
+        if (str != null) {
+            int strLen = str.length();
+            if (strLen < len) {
+                bytes = new byte[len];
+                byte[] b = str.getBytes();
+                for (int i = 0; i < b.length; i++) {
+                    bytes[i] = b[i];
+                }
+                for (int i = b.length; i < bytes.length; i++) {
+                    bytes[i] = 0;
+                }
+            } else if (strLen == len) {
+                bytes = str.getBytes();
+            } else {
+                bytes = new byte[len];
+                byte[] b = str.getBytes();
+                for (int i = 0; i < len; i++) {
+                    bytes[i] = b[i];
+                }
+            }
+        } else {
+            bytes = new byte[len];
+            for (int i = 0; i < bytes.length; i++) {
+                bytes[i] = 0;
+            }
+        }
+        return bytes;
+    }
+
+    private static synchronized byte getSmsSeq() {
+        if (smsSeq >= 127) {
+            return MessageUtil.smsSeq = 0;
+        }
+        return smsSeq++;
+    }
+
+    public static byte[][] subMessage(byte[] strByte, int length) {
+        if (strByte == null) {
+            return (byte[][]) null;
+        }
+        byte[][] result = (byte[][]) null;
+        int count = (strByte.length - 1) / (length - 6) + 1;
+        result = new byte[count][];
+        int index = 0;
+        byte smsSeq = getSmsSeq();
+        for (int i = 0; i < count; i++) {
+            byte[] b = null;
+            if (index + (length - 6) <= strByte.length) {
+                b = new byte[length];
+            } else {
+                b = new byte[strByte.length - index + 6];
+            }
+            b[0] = 5;
+            b[1] = 0;
+            b[2] = 3;
+            b[3] = smsSeq;
+            b[4] = ((byte) count);
+            b[5] = ((byte) (i + 1));
+            for (int j = 6; j < b.length; j++) {
+                b[j] = strByte[index];
+                index++;
+            }
+            result[i] = b;
+        }
+        return result;
+    }
+
+    public static byte[][] buildWAPPush(String message, String url)
+            throws UnsupportedEncodingException {
+        byte[] urlBytes = url.getBytes("UTF-8");
+        byte[] messageBytes = message.getBytes("UTF-8");
+        IoBuffer buffer = IoBuffer.allocate(140).setAutoExpand(true);
+        buffer.put(WBXML_HEADER);
+        buffer.put(urlBytes);
+        buffer.put(END1);
+        buffer.put(messageBytes);
+        buffer.put(END2);
+        buffer.flip();
+        int contentLength = buffer.limit();
+
+        int submitCount = contentLength / 128;
+        if (contentLength % 128 != 0) {
+            submitCount++;
+        }
+        byte[][] result = new byte[submitCount][];
+        byte smsSeq = getSmsSeq();
+        for (int i = 0; i < submitCount; i++) {
+            int readLength = contentLength - buffer.position();
+            if (readLength > 128) {
+                readLength = 128;
+            }
+            IoBuffer buf1 = IoBuffer.allocate(12 + readLength);
+            buf1.put((byte) 11);
+            buf1.put(IE_PORT_APP);
+
+            buf1.put(new byte[] { 0, 3, smsSeq, (byte) submitCount, (byte) (i + 1) });
+            buf1.put(buffer.getSlice(readLength));
+            result[i] = buf1.array();
+        }
+        return result;
+    }
+}

+ 26 - 0
src/main/java/com/nokia/sms/sgip/codec/SgipCodecFactory.java

@@ -0,0 +1,26 @@
+package com.nokia.sms.sgip.codec;
+
+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 SgipCodecFactory implements ProtocolCodecFactory {
+    private ProtocolDecoder decoder;
+    private ProtocolEncoder encoder;
+
+    public SgipCodecFactory() {
+        this.decoder = new SgipMessageDecoder();
+        this.encoder = new SgipMessageEncoder();
+    }
+
+    public ProtocolDecoder getDecoder(IoSession session)
+            throws Exception {
+        return this.decoder;
+    }
+
+    public ProtocolEncoder getEncoder(IoSession session)
+            throws Exception {
+        return this.encoder;
+    }
+}

+ 97 - 0
src/main/java/com/nokia/sms/sgip/codec/SgipMessageDecoder.java

@@ -0,0 +1,97 @@
+package com.nokia.sms.sgip.codec;
+
+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;
+
+import com.nokia.sms.sgip.exception.ReadErrorException;
+import com.nokia.sms.sgip.message.BindMessage;
+import com.nokia.sms.sgip.message.BindResponseMessage;
+import com.nokia.sms.sgip.message.DeliverMessage;
+import com.nokia.sms.sgip.message.DeliverResponseMessage;
+import com.nokia.sms.sgip.message.Head;
+import com.nokia.sms.sgip.message.ReportMessage;
+import com.nokia.sms.sgip.message.ReportResponseMessage;
+import com.nokia.sms.sgip.message.SgipMessage;
+import com.nokia.sms.sgip.message.SubmitMessage;
+import com.nokia.sms.sgip.message.SubmitResponseMessage;
+import com.nokia.sms.sgip.message.UnBindMessage;
+import com.nokia.sms.sgip.message.UnBindResponseMessage;
+import com.nokia.sms.sgip.message.UnknowMessage;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SgipMessageDecoder extends CumulativeProtocolDecoder {
+    protected boolean doDecode(IoSession session, IoBuffer buffer, ProtocolDecoderOutput out)
+            throws Exception {
+        int oldPosition = buffer.position();
+
+        int msgLen = buffer.getInt();
+        if (buffer.remaining() >= msgLen - 4) {
+            buffer.position(oldPosition);
+            Head head = new Head();
+            head.parse(buffer);
+            SgipMessage message = null;
+            switch (head.getCommandId()) {
+                case 1:
+                    message = new BindMessage();
+                    break;
+                case -2147483647:
+                    message = new BindResponseMessage();
+                    break;
+                case 3:
+                    message = new SubmitMessage();
+                    break;
+                case -2147483645:
+                    message = new SubmitResponseMessage();
+                    break;
+                case 4:
+                    message = new DeliverMessage();
+                    break;
+                case -2147483644:
+                    message = new DeliverResponseMessage();
+                    break;
+                case 5:
+                    message = new ReportMessage();
+                    break;
+                case -2147483643:
+                    message = new ReportResponseMessage();
+                    break;
+                case 2:
+                    message = new UnBindMessage();
+                    break;
+                case -2147483646:
+                    message = new UnBindResponseMessage();
+                    break;
+                default:
+                    message = new UnknowMessage();
+                    byte count = ((Byte) session.getAttribute("readErrorCount")).byteValue();
+                    count = (byte) (count + 1);
+                    if (count >= 2) {
+                        throw new ReadErrorException(
+                                "MessageLength=" + msgLen + ",buffer.remaining=" + buffer.remaining());
+                    }
+                    count = (byte) (count + 1);
+                    session.setAttribute("readErrorCount", Byte.valueOf(count));
+            }
+            message.parse(head, buffer);
+            out.write(message);
+            session.setAttribute("readErrorCount", Byte.valueOf((byte) 0));
+            return true;
+        }
+        buffer.position(oldPosition);
+        log.warn("MessageLength=" + msgLen + ",buffer.remaining=" + buffer.remaining() + ",HexDump="
+                + buffer.getHexDump());
+        buffer.position(oldPosition);
+        byte count = ((Byte) session.getAttribute("readErrorCount")).byteValue();
+        count = (byte) (count + 1);
+        if (count >= 2) {
+            throw new ReadErrorException("MessageLength=" + msgLen + ",buffer.remaining=" + buffer.remaining());
+        }
+        count = (byte) (count + 1);
+        session.setAttribute("readErrorCount", Byte.valueOf(count));
+        return false;
+    }
+}

+ 18 - 0
src/main/java/com/nokia/sms/sgip/codec/SgipMessageEncoder.java

@@ -0,0 +1,18 @@
+package com.nokia.sms.sgip.codec;
+
+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.nokia.sms.sgip.message.SgipMessage;
+
+public class SgipMessageEncoder extends ProtocolEncoderAdapter {
+    public void encode(IoSession session, Object object, ProtocolEncoderOutput out)
+            throws Exception {
+        SgipMessage message = (SgipMessage) object;
+        IoBuffer buffer = message.getBuffer();
+        out.write(buffer);
+        out.flush();
+    }
+}

+ 20 - 0
src/main/java/com/nokia/sms/sgip/exception/ReadErrorException.java

@@ -0,0 +1,20 @@
+package com.nokia.sms.sgip.exception;
+
+public class ReadErrorException extends Exception {
+    private static final long serialVersionUID = 1915669292177074242L;
+
+    public ReadErrorException() {
+    }
+
+    public ReadErrorException(String message) {
+        super(message);
+    }
+
+    public ReadErrorException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ReadErrorException(Throwable cause) {
+        super(cause);
+    }
+}

+ 201 - 0
src/main/java/com/nokia/sms/sgip/filter/SGIPLoggingFilter.java

@@ -0,0 +1,201 @@
+package com.nokia.sms.sgip.filter;
+
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.mina.core.filterchain.IoFilter;
+import org.apache.mina.core.filterchain.IoFilterAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.core.write.WriteRequest;
+import org.apache.mina.filter.logging.LogLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SGIPLoggingFilter extends IoFilterAdapter {
+    private final String name;
+    private final Logger logger;
+    private LogLevel exceptionCaughtLevel = LogLevel.WARN;
+    private LogLevel messageSentLevel = LogLevel.INFO;
+    private LogLevel messageReceivedLevel = LogLevel.INFO;
+    private LogLevel sessionCreatedLevel = LogLevel.INFO;
+    private LogLevel sessionOpenedLevel = LogLevel.INFO;
+    private LogLevel sessionIdleLevel = LogLevel.INFO;
+    private LogLevel sessionClosedLevel = LogLevel.INFO;
+
+    public SGIPLoggingFilter() {
+        this(SGIPLoggingFilter.class.getName());
+    }
+
+    public SGIPLoggingFilter(Class<?> clazz) {
+        this(clazz.getName());
+    }
+
+    public SGIPLoggingFilter(String name) {
+        if (name == null) {
+            this.name = SGIPLoggingFilter.class.getName();
+        } else {
+            this.name = name;
+        }
+        this.logger = LoggerFactory.getLogger(this.name);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+  private void log(LogLevel eventLevel, String message, Throwable cause)
+  {
+    switch (eventLevel.ordinal())
+    {
+    case 1: 
+      this.logger.trace(message, cause);return;
+    case 2: 
+      this.logger.debug(message, cause);return;
+    case 3: 
+      this.logger.info(message, cause);return;
+    case 4: 
+      this.logger.warn(message, cause);return;
+    case 5: 
+      this.logger.error(message, cause);return;
+    }
+  }
+
+  private void log(LogLevel eventLevel, String message, Object param)
+  {
+    switch (eventLevel.ordinal())
+    {
+    case 1: 
+      this.logger.trace(message, param);return;
+    case 2: 
+      this.logger.debug(message, param);return;
+    case 3: 
+      this.logger.info(message, param);return;
+    case 4: 
+      this.logger.warn(message, param);return;
+    case 5: 
+      this.logger.error(message, param);return;
+    }
+  }
+
+  private void log(LogLevel eventLevel, String message)
+  {
+    switch (eventLevel.ordinal())
+    {
+    case 1: 
+      this.logger.trace(message);return;
+    case 2: 
+      this.logger.debug(message);return;
+    case 3: 
+      this.logger.info(message);return;
+    case 4: 
+      this.logger.warn(message);return;
+    case 5: 
+      this.logger.error(message);return;
+    }
+  }
+
+    public void exceptionCaught(IoFilter.NextFilter nextFilter, IoSession session, Throwable cause)
+            throws Exception {
+        log(this.exceptionCaughtLevel, "EXCEPTION :", cause);
+        nextFilter.exceptionCaught(session, cause);
+    }
+
+    public void messageReceived(IoFilter.NextFilter nextFilter, IoSession session, Object message)
+            throws Exception {
+        if (IoBuffer.class.isAssignableFrom(message.getClass())) {
+            IoBuffer buffer = (IoBuffer) message;
+            int oldPosition = buffer.position();
+            int lengthLimit = buffer.getInt();
+            buffer.position(oldPosition);
+            log(this.messageReceivedLevel, "RECEIVED: {}", "HexDump[" + buffer.getHexDump(lengthLimit) + "]");
+        } else {
+            log(this.messageReceivedLevel, "RECEIVED: {}", message);
+        }
+        nextFilter.messageReceived(session, message);
+    }
+
+    public void messageSent(IoFilter.NextFilter nextFilter, IoSession session, WriteRequest writeRequest)
+            throws Exception {
+        log(this.messageSentLevel, "SENT: {}", writeRequest.getMessage());
+        nextFilter.messageSent(session, writeRequest);
+    }
+
+    public void sessionCreated(IoFilter.NextFilter nextFilter, IoSession session)
+            throws Exception {
+        log(this.sessionCreatedLevel, "CREATED " + session.getRemoteAddress());
+        nextFilter.sessionCreated(session);
+    }
+
+    public void sessionOpened(IoFilter.NextFilter nextFilter, IoSession session)
+            throws Exception {
+        log(this.sessionOpenedLevel, "OPENED " + session.getRemoteAddress());
+        nextFilter.sessionOpened(session);
+    }
+
+    public void sessionIdle(IoFilter.NextFilter nextFilter, IoSession session, IdleStatus status)
+            throws Exception {
+        log(this.sessionIdleLevel, "IDLE");
+        nextFilter.sessionIdle(session, status);
+    }
+
+    public void sessionClosed(IoFilter.NextFilter nextFilter, IoSession session)
+            throws Exception {
+        log(this.sessionClosedLevel, "CLOSED " + session.getRemoteAddress());
+        nextFilter.sessionClosed(session);
+    }
+
+    public void setExceptionCaughtLogLevel(LogLevel level) {
+        this.exceptionCaughtLevel = level;
+    }
+
+    public LogLevel getExceptionCaughtLogLevel() {
+        return this.exceptionCaughtLevel;
+    }
+
+    public void setMessageReceivedLogLevel(LogLevel level) {
+        this.messageReceivedLevel = level;
+    }
+
+    public LogLevel getMessageReceivedLogLevel() {
+        return this.messageReceivedLevel;
+    }
+
+    public void setMessageSentLogLevel(LogLevel level) {
+        this.messageSentLevel = level;
+    }
+
+    public LogLevel getMessageSentLogLevel() {
+        return this.messageSentLevel;
+    }
+
+    public void setSessionCreatedLogLevel(LogLevel level) {
+        this.sessionCreatedLevel = level;
+    }
+
+    public LogLevel getSessionCreatedLogLevel() {
+        return this.sessionCreatedLevel;
+    }
+
+    public void setSessionOpenedLogLevel(LogLevel level) {
+        this.sessionOpenedLevel = level;
+    }
+
+    public LogLevel getSessionOpenedLogLevel() {
+        return this.sessionOpenedLevel;
+    }
+
+    public void setSessionIdleLogLevel(LogLevel level) {
+        this.sessionIdleLevel = level;
+    }
+
+    public LogLevel getSessionIdleLogLevel() {
+        return this.sessionIdleLevel;
+    }
+
+    public void setSessionClosedLogLevel(LogLevel level) {
+        this.sessionClosedLevel = level;
+    }
+
+    public LogLevel getSessionClosedLogLevel() {
+        return this.sessionClosedLevel;
+    }
+}

+ 100 - 0
src/main/java/com/nokia/sms/sgip/message/BindMessage.java

@@ -0,0 +1,100 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class BindMessage extends SgipMessage {
+    public static final int COMMAND_ID = 1;
+    private byte loginType;
+    private String loginName;
+    private String loginPassword;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(1);
+        this.head.setMessageLength(61);
+        IoBuffer buffer = IoBuffer.allocate(61);
+        buffer.put(this.head.getBuffer());
+        buffer.put(this.loginType);
+        int oldPosition = buffer.position();
+        buffer.put(this.loginName.getBytes());
+        buffer.position(oldPosition + 16);
+        oldPosition = buffer.position();
+        buffer.put(this.loginPassword.getBytes());
+        buffer.position(oldPosition + 16);
+        oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer) throws IOException {
+        this.loginType = ioBuffer.get();
+        this.loginName = ioBuffer.getString(16, MessageUtil.gbkDecoder);
+        this.loginPassword = ioBuffer.getString(16, MessageUtil.gbkDecoder);
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public byte getLoginType() {
+        return this.loginType;
+    }
+
+    public void setLoginType(byte loginType) {
+        this.loginType = loginType;
+    }
+
+    public String getLoginName() {
+        return this.loginName;
+    }
+
+    public void setLoginName(String loginName) {
+        this.loginName = loginName;
+    }
+
+    public String getLoginPassword() {
+        return this.loginPassword;
+    }
+
+    public void setLoginPassword(String loginPassword) {
+        this.loginPassword = loginPassword;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "BindMessage [head=" + this.head + ", loginName=" + this.loginName + ", loginPassword="
+                + this.loginPassword + ", loginType=" + this.loginType + ", reserve=" + this.reserve + "]";
+    }
+
+    public static void main(String[] args) {
+        BindMessage message = new BindMessage();
+        message.setLoginName("aaa");
+        message.setLoginPassword("bbb");
+        message.setLoginType((byte) 1);
+        IoBuffer buffer = message.getBuffer();
+        System.out.println(buffer.limit());
+        BindMessage message2 = new BindMessage();
+        Head head = new Head();
+        head.parse(buffer);
+        try {
+            message2.parse(head, buffer);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        System.out.println(message2);
+    }
+}

+ 57 - 0
src/main/java/com/nokia/sms/sgip/message/BindResponseMessage.java

@@ -0,0 +1,57 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class BindResponseMessage extends SgipMessage {
+    public static final int COMMAND_ID = -2147483647;
+    private byte operateResult;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(-2147483647);
+        this.head.setMessageLength(29);
+        IoBuffer buffer = IoBuffer.allocate(29);
+        buffer.put(this.head.getBuffer());
+        buffer.put(this.operateResult);
+        int oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.operateResult = ioBuffer.get();
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public byte getOperateResult() {
+        return this.operateResult;
+    }
+
+    public void setOperateResult(byte operateResult) {
+        this.operateResult = operateResult;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "BindResponseMessage [head=" + this.head + ", operateResult=" + this.operateResult + ", reserve="
+                + this.reserve + "]";
+    }
+}

+ 174 - 0
src/main/java/com/nokia/sms/sgip/message/DeliverMessage.java

@@ -0,0 +1,174 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.CharsetDecoder;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class DeliverMessage extends SgipMessage {
+    public static final int COMMAND_ID = 4;
+    private String userNumber;
+    private String spNumber;
+    private byte tppid;
+    private byte tpudhi;
+    private byte messageCoding;
+    private int messageLength;
+    private String messageContent;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        IoBuffer buffer = IoBuffer.allocate(200).setAutoExpand(true);
+        buffer.position(20);
+        int oldPosition = buffer.position();
+        buffer.put(this.userNumber.getBytes());
+        buffer.position(oldPosition + 21);
+        oldPosition = buffer.position();
+        buffer.put(this.spNumber.getBytes());
+        buffer.position(oldPosition + 21);
+        buffer.put(this.tppid);
+        buffer.put(this.tpudhi);
+        buffer.put(this.messageCoding);
+        byte[] content = null;
+        try {
+            if (this.messageCoding == 8) {
+                content = this.messageContent.getBytes("UnicodeBigUnmarked");
+            } else if (this.messageCoding == 0) {
+                content = this.messageContent.getBytes("ASCII");
+            } else {
+                content = this.messageContent.getBytes("GBK");
+            }
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        this.messageLength = content.length;
+        buffer.putInt(this.messageLength);
+        buffer.put(content);
+        oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        oldPosition = buffer.position();
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(4);
+        this.head.setMessageLength(oldPosition);
+        buffer.position(0);
+        buffer.put(this.head.getBuffer());
+        buffer.position(oldPosition);
+
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.userNumber = ioBuffer.getString(21, MessageUtil.gbkDecoder);
+        this.spNumber = ioBuffer.getString(21, MessageUtil.gbkDecoder);
+        this.tppid = ioBuffer.get();
+        this.tpudhi = ioBuffer.get();
+        this.messageCoding = ioBuffer.get();
+        this.messageLength = ioBuffer.getInt();
+        CharsetDecoder decoder = null;
+        if (this.messageCoding == 8) {
+            decoder = MessageUtil.ucs2Decoder;
+        } else {
+            decoder = MessageUtil.gbkDecoder;
+        }
+        this.messageContent = ioBuffer.getString(this.messageLength, decoder);
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public byte[] getmessageContenByBytes() {
+        byte[] bytes = null;
+        try {
+            if (this.messageContent == null) {
+                return null;
+            }
+            if (this.messageCoding == 8) {
+                bytes = this.messageContent.getBytes("UnicodeBigUnmarked");
+            } else if (this.messageCoding == 0) {
+                bytes = this.messageContent.getBytes("ASCII");
+            } else {
+                bytes = this.messageContent.getBytes("GBK");
+            }
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return bytes;
+    }
+
+    public String getUserNumber() {
+        return this.userNumber;
+    }
+
+    public void setUserNumber(String userNumber) {
+        this.userNumber = userNumber;
+    }
+
+    public String getSpNumber() {
+        return this.spNumber;
+    }
+
+    public void setSpNumber(String spNumber) {
+        this.spNumber = spNumber;
+    }
+
+    public byte getTppid() {
+        return this.tppid;
+    }
+
+    public void setTppid(byte tppid) {
+        this.tppid = tppid;
+    }
+
+    public byte getTpudhi() {
+        return this.tpudhi;
+    }
+
+    public void setTpudhi(byte tpudhi) {
+        this.tpudhi = tpudhi;
+    }
+
+    public byte getMessageCoding() {
+        return this.messageCoding;
+    }
+
+    public void setMessageCoding(byte messageCoding) {
+        this.messageCoding = messageCoding;
+    }
+
+    public int getMessageLength() {
+        return this.messageLength;
+    }
+
+    public void setMessageLength(int messageLength) {
+        this.messageLength = messageLength;
+    }
+
+    public String getMessageContent() {
+        return this.messageContent;
+    }
+
+    public void setMessageContent(String messageContent) {
+        this.messageContent = messageContent;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "DeliverMessage [head=" + this.head + ", messageContent=" + this.messageContent + ", messageLength="
+                + this.messageLength + ", reserve=" + this.reserve + ", spNumber=" + this.spNumber + ", tppid="
+                + this.tppid + ", tpudhi=" + this.tpudhi + ", userNumber=" + this.userNumber + ",messageCoding="
+                + this.messageCoding + "]";
+    }
+}

+ 57 - 0
src/main/java/com/nokia/sms/sgip/message/DeliverResponseMessage.java

@@ -0,0 +1,57 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class DeliverResponseMessage extends SgipMessage {
+    public static final int COMMAND_ID = -2147483644;
+    private byte operateResult;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(-2147483644);
+        this.head.setMessageLength(29);
+        IoBuffer buffer = IoBuffer.allocate(29);
+        buffer.put(this.head.getBuffer());
+        buffer.put(this.operateResult);
+        int oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.operateResult = ioBuffer.get();
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public void setOperateResult(byte result) {
+        this.operateResult = result;
+    }
+
+    public byte getOperateResult() {
+        return this.operateResult;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "DeliverResponseMessage [head=" + this.head + ",operateResult=" + this.operateResult + ", reserve="
+                + this.reserve + "]";
+    }
+}

+ 75 - 0
src/main/java/com/nokia/sms/sgip/message/Head.java

@@ -0,0 +1,75 @@
+package com.nokia.sms.sgip.message;
+
+import java.util.Arrays;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class Head {
+    private int messageLength;
+    private int commandId;
+    private int[] flowId;
+
+    public IoBuffer getBuffer() {
+        IoBuffer ioBuffer = IoBuffer.allocate(20);
+        ioBuffer.putInt(this.messageLength);
+        ioBuffer.putInt(this.commandId);
+        if (this.flowId == null) {
+            this.flowId = MessageUtil.getFlowId();
+        }
+        ioBuffer.putInt(this.flowId[0]);
+        ioBuffer.putInt(this.flowId[1]);
+        ioBuffer.putInt(this.flowId[2]);
+        return ioBuffer.flip();
+    }
+
+    public void parse(IoBuffer ioBuffer) {
+        this.messageLength = ioBuffer.getInt();
+        this.commandId = ioBuffer.getInt();
+        this.flowId = new int[3];
+        this.flowId[0] = ioBuffer.getInt();
+        this.flowId[1] = ioBuffer.getInt();
+        this.flowId[2] = ioBuffer.getInt();
+    }
+
+    public int getMessageLength() {
+        return this.messageLength;
+    }
+
+    public void setMessageLength(int messageLength) {
+        this.messageLength = messageLength;
+    }
+
+    public int getCommandId() {
+        return this.commandId;
+    }
+
+    public void setCommandId(int commandId) {
+        this.commandId = commandId;
+    }
+
+    public int[] getFlowId() {
+        return this.flowId;
+    }
+
+    public void setFlowId(int[] flowId) {
+        this.flowId = flowId;
+    }
+
+    public String toString() {
+        return "Head [messageLength=" + this.messageLength + ",commandId=0x" + Integer.toHexString(this.commandId)
+                + ",flowId=" + Arrays.toString(this.flowId) + "]";
+    }
+
+    public String getStrFlowId() {
+        if ((this.flowId != null) && (this.flowId.length == 3)) {
+            StringBuilder sb = new StringBuilder(12);
+            sb.append(this.flowId[0]);
+            sb.append(this.flowId[1]);
+            sb.append(this.flowId[2]);
+            return sb.toString();
+        }
+        return null;
+    }
+}

+ 110 - 0
src/main/java/com/nokia/sms/sgip/message/ReportMessage.java

@@ -0,0 +1,110 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class ReportMessage extends SgipMessage {
+    public static final int COMMAND_ID = 5;
+    private int[] submitSN;
+    private byte reportType;
+    private String userNumber;
+    private byte state;
+    private byte errorCode;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(5);
+        this.head.setMessageLength(64);
+        IoBuffer buffer = IoBuffer.allocate(64);
+        buffer.put(this.head.getBuffer());
+        buffer.putInt(this.submitSN[0]);
+        buffer.putInt(this.submitSN[1]);
+        buffer.putInt(this.submitSN[2]);
+        buffer.put(this.reportType);
+        int oldPosition = buffer.position();
+        buffer.put(this.userNumber.getBytes());
+        buffer.position(oldPosition + 21);
+        buffer.put(this.state);
+        buffer.put(this.errorCode);
+        oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.submitSN = new int[3];
+        this.submitSN[0] = ioBuffer.getInt();
+        this.submitSN[1] = ioBuffer.getInt();
+        this.submitSN[2] = ioBuffer.getInt();
+        this.reportType = ioBuffer.get();
+        this.userNumber = ioBuffer.getString(21, MessageUtil.gbkDecoder);
+        this.state = ioBuffer.get();
+        this.errorCode = ioBuffer.get();
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public int[] getSubmitSN() {
+        return this.submitSN;
+    }
+
+    public void setSubmitSN(int[] submitSN) {
+        this.submitSN = submitSN;
+    }
+
+    public int getReportType() {
+        return this.reportType;
+    }
+
+    public void setReportType(byte reportType) {
+        this.reportType = reportType;
+    }
+
+    public String getUserNumber() {
+        return this.userNumber;
+    }
+
+    public void setUserNumber(String userNumber) {
+        this.userNumber = userNumber;
+    }
+
+    public int getState() {
+        return this.state;
+    }
+
+    public void setState(byte state) {
+        this.state = state;
+    }
+
+    public int getErrorCode() {
+        return this.errorCode;
+    }
+
+    public void setErrorCode(byte errorCode) {
+        this.errorCode = errorCode;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "ReportMessage [head=" + this.head + ",reportType=" + this.reportType + ",reserve=" + this.reserve
+                + ",state=" + this.state + ",submitSN=" + Arrays.toString(this.submitSN) + ",userNumber="
+                + this.userNumber + ",errorCode=" + this.errorCode + "]";
+    }
+}

+ 57 - 0
src/main/java/com/nokia/sms/sgip/message/ReportResponseMessage.java

@@ -0,0 +1,57 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class ReportResponseMessage extends SgipMessage {
+    public static final int COMMAND_ID = -2147483643;
+    private byte operateResult;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(-2147483643);
+        this.head.setMessageLength(29);
+        IoBuffer buffer = IoBuffer.allocate(29);
+        buffer.put(this.head.getBuffer());
+        buffer.put(this.operateResult);
+        int oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.operateResult = ioBuffer.get();
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public void setOperateResult(byte result) {
+        this.operateResult = result;
+    }
+
+    public byte getOperateResult() {
+        return this.operateResult;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "ReportResponseMessage [head=" + this.head + ",operateResult=" + this.operateResult + ", reserve="
+                + this.reserve + "]";
+    }
+}

+ 33 - 0
src/main/java/com/nokia/sms/sgip/message/SendResult.java

@@ -0,0 +1,33 @@
+package com.nokia.sms.sgip.message;
+
+import java.util.Arrays;
+
+public class SendResult {
+    private int[] flowId;
+    private byte result;
+
+    public SendResult(int[] flowId, byte result) {
+        this.flowId = flowId;
+        this.result = result;
+    }
+
+    public int[] getFlowId() {
+        return this.flowId;
+    }
+
+    public void setFlowId(int[] flowId) {
+        this.flowId = flowId;
+    }
+
+    public byte getResult() {
+        return this.result;
+    }
+
+    public void setResult(byte result) {
+        this.result = result;
+    }
+
+    public String toString() {
+        return "MessageResult [flowId=" + Arrays.toString(this.flowId) + ", result=" + this.result + "]";
+    }
+}

+ 28 - 0
src/main/java/com/nokia/sms/sgip/message/SgipMessage.java

@@ -0,0 +1,28 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+public abstract class SgipMessage {
+    protected Head head;
+
+    public abstract IoBuffer getBuffer();
+
+    public void parse(Head head, IoBuffer ioBuffer)
+            throws IOException {
+        setHead(head);
+        parseBody(ioBuffer);
+    }
+
+    public void setHead(Head head) {
+        this.head = head;
+    }
+
+    public Head getHead() {
+        return this.head;
+    }
+
+    public abstract void parseBody(IoBuffer paramIoBuffer)
+            throws IOException;
+}

+ 334 - 0
src/main/java/com/nokia/sms/sgip/message/SubmitMessage.java

@@ -0,0 +1,334 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class SubmitMessage extends SgipMessage {
+    public static final int COMMAND_ID = 3;
+    private String spNumber;
+    private String chargeNumber;
+    private byte userCount;
+    private String[] userNumber;
+    private String corpId;
+    private String serviceType;
+    private byte feeType;
+    private String feeValue;
+    private String givenValue;
+    private byte agentFlag;
+    private byte morelatetoMTFlag;
+    private byte priority;
+    private String expireTime;
+    private String scheduleTime;
+    private byte reportFlag;
+    private byte tppid;
+    private byte tpudhi;
+    private byte messageCoding;
+    private byte messageType;
+    private int messageLength;
+    private byte[] messageContent;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        IoBuffer buffer = IoBuffer.allocate(200).setAutoExpand(true);
+        buffer.position(20);
+        int oldPosition = buffer.position();
+        buffer.put(this.spNumber.getBytes());
+        buffer.position(oldPosition + 21);
+        oldPosition = buffer.position();
+        buffer.put(this.chargeNumber.getBytes());
+        buffer.position(oldPosition + 21);
+        this.userCount = ((byte) this.userNumber.length);
+        buffer.put(this.userCount);
+        for (int i = 0; i < this.userNumber.length; i++) {
+            oldPosition = buffer.position();
+            buffer.put(this.userNumber[i].getBytes());
+            buffer.position(oldPosition + 21);
+        }
+        oldPosition = buffer.position();
+        buffer.put(this.corpId.getBytes());
+        buffer.position(oldPosition + 5);
+        oldPosition = buffer.position();
+        buffer.put(this.serviceType.getBytes());
+        buffer.position(oldPosition + 10);
+        buffer.put(this.feeType);
+        oldPosition = buffer.position();
+        buffer.put(this.feeValue.getBytes());
+        buffer.position(oldPosition + 6);
+        oldPosition = buffer.position();
+        buffer.put(this.givenValue.getBytes());
+        buffer.position(oldPosition + 6);
+        buffer.put(this.agentFlag);
+        buffer.put(this.morelatetoMTFlag);
+        buffer.put(this.priority);
+        oldPosition = buffer.position();
+        if (this.expireTime != null) {
+            buffer.put(this.expireTime.getBytes());
+        }
+        buffer.position(oldPosition + 16);
+        oldPosition = buffer.position();
+        if (this.scheduleTime != null) {
+            buffer.put(this.scheduleTime.getBytes());
+        }
+        buffer.position(oldPosition + 16);
+        buffer.put(this.reportFlag);
+        buffer.put(this.tppid);
+        buffer.put(this.tpudhi);
+        buffer.put(this.messageCoding);
+
+        buffer.put(this.messageType);
+        this.messageLength = this.messageContent.length;
+        buffer.putInt(this.messageLength);
+        buffer.put(this.messageContent);
+        oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        oldPosition = buffer.position();
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(3);
+        this.head.setMessageLength(oldPosition);
+        buffer.position(0);
+        buffer.put(this.head.getBuffer());
+        buffer.position(oldPosition);
+
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.spNumber = ioBuffer.getString(21, MessageUtil.gbkDecoder);
+        this.chargeNumber = ioBuffer.getString(21, MessageUtil.gbkDecoder);
+        this.userCount = ioBuffer.get();
+        this.userNumber = new String[this.userCount];
+        for (int i = 0; i < this.userCount; i++) {
+            this.userNumber[i] = ioBuffer.getString(21, MessageUtil.gbkDecoder);
+        }
+        this.corpId = ioBuffer.getString(5, MessageUtil.gbkDecoder);
+        this.serviceType = ioBuffer.getString(10, MessageUtil.gbkDecoder);
+        this.feeType = ioBuffer.get();
+        this.feeValue = ioBuffer.getString(6, MessageUtil.gbkDecoder);
+        this.givenValue = ioBuffer.getString(6, MessageUtil.gbkDecoder);
+        this.agentFlag = ioBuffer.get();
+        this.morelatetoMTFlag = ioBuffer.get();
+        this.priority = ioBuffer.get();
+        this.expireTime = ioBuffer.getString(16, MessageUtil.gbkDecoder);
+        this.scheduleTime = ioBuffer.getString(16, MessageUtil.gbkDecoder);
+        this.reportFlag = ioBuffer.get();
+        this.tppid = ioBuffer.get();
+        this.tpudhi = ioBuffer.get();
+        this.messageCoding = ioBuffer.get();
+        this.messageType = ioBuffer.get();
+        this.messageLength = ioBuffer.getInt();
+        this.messageContent = new byte[this.messageLength];
+        ioBuffer.get(this.messageContent);
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public String getSpNumber() {
+        return this.spNumber;
+    }
+
+    public void setSpNumber(String spNumber) {
+        this.spNumber = spNumber;
+    }
+
+    public String getChargeNumber() {
+        return this.chargeNumber;
+    }
+
+    public void setChargeNumber(String chargeNumber) {
+        this.chargeNumber = chargeNumber;
+    }
+
+    public byte getUserCount() {
+        return this.userCount;
+    }
+
+    public void setUserCount(byte userCount) {
+        this.userCount = userCount;
+    }
+
+    public String[] getUserNumber() {
+        return this.userNumber;
+    }
+
+    public void setUserNumber(String[] userNumber) {
+        this.userNumber = userNumber;
+    }
+
+    public String getCorpId() {
+        return this.corpId;
+    }
+
+    public void setCorpId(String corpId) {
+        this.corpId = corpId;
+    }
+
+    public String getServiceType() {
+        return this.serviceType;
+    }
+
+    public void setServiceType(String serviceType) {
+        this.serviceType = serviceType;
+    }
+
+    public byte getFeeType() {
+        return this.feeType;
+    }
+
+    public void setFeeType(byte feeType) {
+        this.feeType = feeType;
+    }
+
+    public String getFeeValue() {
+        return this.feeValue;
+    }
+
+    public void setFeeValue(String feeValue) {
+        this.feeValue = feeValue;
+    }
+
+    public String getGivenValue() {
+        return this.givenValue;
+    }
+
+    public void setGivenValue(String givenValue) {
+        this.givenValue = givenValue;
+    }
+
+    public byte getAgentFlag() {
+        return this.agentFlag;
+    }
+
+    public void setAgentFlag(byte agentFlag) {
+        this.agentFlag = agentFlag;
+    }
+
+    public byte getMorelatetoMTFlag() {
+        return this.morelatetoMTFlag;
+    }
+
+    public void setMorelatetoMTFlag(byte morelatetoMTFlag) {
+        this.morelatetoMTFlag = morelatetoMTFlag;
+    }
+
+    public byte getPriority() {
+        return this.priority;
+    }
+
+    public void setPriority(byte priority) {
+        this.priority = priority;
+    }
+
+    public String getExpireTime() {
+        return this.expireTime;
+    }
+
+    public void setExpireTime(String expireTime) {
+        this.expireTime = expireTime;
+    }
+
+    public String getScheduleTime() {
+        return this.scheduleTime;
+    }
+
+    public void setScheduleTime(String scheduleTime) {
+        this.scheduleTime = scheduleTime;
+    }
+
+    public byte getReportFlag() {
+        return this.reportFlag;
+    }
+
+    public void setReportFlag(byte reportFlag) {
+        this.reportFlag = reportFlag;
+    }
+
+    public byte getTppid() {
+        return this.tppid;
+    }
+
+    public void setTppid(byte tppid) {
+        this.tppid = tppid;
+    }
+
+    public byte getTpudhi() {
+        return this.tpudhi;
+    }
+
+    public void setTpudhi(byte tpudhi) {
+        this.tpudhi = tpudhi;
+    }
+
+    public byte getMessageCoding() {
+        return this.messageCoding;
+    }
+
+    public void setMessageCoding(byte messageCoding) {
+        this.messageCoding = messageCoding;
+    }
+
+    public byte getMessageType() {
+        return this.messageType;
+    }
+
+    public void setMessageType(byte messageType) {
+        this.messageType = messageType;
+    }
+
+    public int getMessageLength() {
+        return this.messageLength;
+    }
+
+    public void setMessageLength(int messageLength) {
+        this.messageLength = messageLength;
+    }
+
+    public byte[] getMessageContent() {
+        return this.messageContent;
+    }
+
+    public void setMessageContent(byte[] messageContent) {
+        this.messageContent = messageContent;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        String content = null;
+        try {
+            if (this.messageCoding == 8) {
+                content = new String(this.messageContent, "UnicodeBigUnmarked");
+            } else if (this.messageCoding == 15) {
+                content = new String(this.messageContent, "GBK");
+            } else {
+                content = new String(this.messageContent, "UTF-8");
+            }
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return "SubmitMessage [head=" + this.head + ",spNumber=" + this.spNumber + ",chargeNumber=" + this.chargeNumber
+                + ",userCount=" + this.userCount + ",userNumber=" + Arrays.toString(this.userNumber) + ",corpId="
+                + this.corpId + ",serviceType=" + this.serviceType + ",feeType=" + this.feeType + ",feeValue="
+                + this.feeValue + ",givenValue=" + this.givenValue + ",agentFlag=" + this.agentFlag
+                + ",morelatetoMTFlag=" + this.morelatetoMTFlag + ",priority=" + this.priority + ",expireTime="
+                + this.expireTime + ",scheduleTime=" + this.scheduleTime + ",reportFlag=" + this.reportFlag + ",tppid="
+                + this.tppid + ",tpudhi=" + this.tpudhi + ",messageCoding=" + this.messageCoding + ",messageType="
+                + this.messageType + ",messageLength=" + this.messageLength + ",messageContent=" + content + ",reserve="
+                + this.reserve + "]";
+    }
+}

+ 57 - 0
src/main/java/com/nokia/sms/sgip/message/SubmitResponseMessage.java

@@ -0,0 +1,57 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+import com.nokia.sms.sgip.codec.MessageUtil;
+
+public class SubmitResponseMessage extends SgipMessage {
+    public static final int COMMAND_ID = -2147483645;
+    private byte operateResult;
+    private String reserve;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(-2147483645);
+        this.head.setMessageLength(29);
+        IoBuffer buffer = IoBuffer.allocate(29);
+        buffer.put(this.head.getBuffer());
+        buffer.put(this.operateResult);
+        int oldPosition = buffer.position();
+        if (this.reserve != null) {
+            buffer.put(this.reserve.getBytes());
+        }
+        buffer.position(oldPosition + 8);
+        return buffer.flip();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+        this.operateResult = ioBuffer.get();
+        this.reserve = ioBuffer.getString(8, MessageUtil.gbkDecoder);
+    }
+
+    public void setOperateResult(byte result) {
+        this.operateResult = result;
+    }
+
+    public byte getOperateResult() {
+        return this.operateResult;
+    }
+
+    public String getReserve() {
+        return this.reserve;
+    }
+
+    public void setReserve(String reserve) {
+        this.reserve = reserve;
+    }
+
+    public String toString() {
+        return "SubmitResponseMessage [head=" + this.head + ", operateResult=" + this.operateResult + ", reserve="
+                + this.reserve + "]";
+    }
+}

+ 26 - 0
src/main/java/com/nokia/sms/sgip/message/UnBindMessage.java

@@ -0,0 +1,26 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+public class UnBindMessage extends SgipMessage {
+    public static final int COMMAND_ID = 2;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(2);
+        this.head.setMessageLength(20);
+        return this.head.getBuffer();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+    }
+
+    public String toString() {
+        return "UnBindMessage [head=" + this.head + "]";
+    }
+}

+ 26 - 0
src/main/java/com/nokia/sms/sgip/message/UnBindResponseMessage.java

@@ -0,0 +1,26 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+public class UnBindResponseMessage extends SgipMessage {
+    public static final int COMMAND_ID = -2147483646;
+
+    public IoBuffer getBuffer() {
+        if (this.head == null) {
+            this.head = new Head();
+        }
+        this.head.setCommandId(-2147483646);
+        this.head.setMessageLength(20);
+        return this.head.getBuffer();
+    }
+
+    public void parseBody(IoBuffer ioBuffer)
+            throws IOException {
+    }
+
+    public String toString() {
+        return "UnBindResponseMessage [head=" + this.head + "]";
+    }
+}

+ 27 - 0
src/main/java/com/nokia/sms/sgip/message/UnknowMessage.java

@@ -0,0 +1,27 @@
+package com.nokia.sms.sgip.message;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.mina.core.buffer.IoBuffer;
+
+public class UnknowMessage extends SgipMessage {
+    private byte[] body;
+  
+  public IoBuffer getBuffer()
+  {
+    return null;
+  }
+  
+  public void parseBody(IoBuffer ioBuffer)
+    throws IOException
+  {
+    this.body = new byte[this.head.getMessageLength()];
+    ioBuffer.get(this.body);
+  }
+  
+  public String toString()
+  {
+    return "UnknowCommand [body=" + Arrays.toString(this.body) + ", head=" + this.head + "]";
+  }
+}

+ 7 - 0
src/main/java/com/nokia/sms/sgip/mo/server/Action.java

@@ -0,0 +1,7 @@
+package com.nokia.sms.sgip.mo.server;
+
+import com.nokia.sms.sgip.message.SgipMessage;
+
+public abstract interface Action {
+    public abstract void execute(SgipMessage paramSgipMessage);
+}

+ 23 - 0
src/main/java/com/nokia/sms/sgip/mo/server/BindChecker.java

@@ -0,0 +1,23 @@
+package com.nokia.sms.sgip.mo.server;
+
+import com.nokia.sms.sgip.SgipConfig;
+import com.nokia.sms.sgip.message.BindMessage;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class BindChecker {
+    public static byte checkBindMessage(BindMessage message) {
+        byte result = -1;
+        String loginName = SgipConfig.getConfig().getString("sgip_mo_login_name", "");
+        String loginPasswd = SgipConfig.getConfig().getString("sgip_mo_login_password", "");
+        log.debug("[Config:loginName=" + loginName + ",loginPasswd=" + loginPasswd + "]");
+        if ((loginName.equals(message.getLoginName())) && (loginPasswd.equals(message.getLoginPassword()))) {
+            result = 0;
+        } else {
+            log.warn(message + ".[Config:loginName=" + loginName + ",loginPasswd=" + loginPasswd + "]");
+            result = 1;
+        }
+        return result;
+    }
+}

+ 84 - 0
src/main/java/com/nokia/sms/sgip/mo/server/MOServer.java

@@ -0,0 +1,84 @@
+package com.nokia.sms.sgip.mo.server;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.mina.core.filterchain.IoFilter;
+import org.apache.mina.core.service.IoAcceptor;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.filter.logging.LogLevel;
+import org.apache.mina.filter.logging.LoggingFilter;
+import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.executor.ExecutorFilter;
+import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor;
+
+import com.nokia.sms.sgip.SgipConfig;
+import com.nokia.sms.sgip.codec.SgipCodecFactory;
+import com.nokia.sms.sgip.filter.SGIPLoggingFilter;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MOServer {
+    private CompositeConfiguration config = SgipConfig.getConfig();
+    private IoAcceptor acceptor;
+    private static MOServer moserver;
+
+    public static synchronized MOServer getInstance() {
+        if (moserver == null) {
+            moserver = new MOServer();
+        }
+        return moserver;
+    }
+
+    private MOServer() {
+        this.acceptor = new NioSocketAcceptor();
+        this.acceptor.getSessionConfig().setReadBufferSize(2048);
+        int idleTime = this.config.getInt("sgip_mo_socket_timeout", 30);
+        this.acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, idleTime);
+        try {
+            int codeThread = this.config.getInt("sgip_mo_threadpool_code_thread", 2);
+            int maxThread = this.config.getInt("sgip_mo_threadpool_max_thread", 4);
+
+            IoFilter coderFilter = new ProtocolCodecFilter(new SgipCodecFactory());
+            SGIPLoggingFilter logFilter = new SGIPLoggingFilter();
+
+            logFilter.setExceptionCaughtLogLevel(LogLevel.NONE);
+            logFilter.setSessionCreatedLogLevel(LogLevel.NONE);
+            logFilter.setSessionOpenedLogLevel(LogLevel.NONE);
+            logFilter.setSessionIdleLogLevel(LogLevel.NONE);
+            logFilter.setMessageSentLogLevel(LogLevel.NONE);
+            logFilter.setMessageReceivedLogLevel(LogLevel.DEBUG);
+            logFilter.setSessionClosedLogLevel(LogLevel.NONE);
+            this.acceptor.getFilterChain().addLast("logFilter1", logFilter);
+            this.acceptor.getFilterChain().addLast("coderFilter", coderFilter);
+            this.acceptor.getFilterChain().addLast("logger", new LoggingFilter());
+            this.acceptor.setHandler(new MOServerHandler());
+            this.acceptor.getFilterChain().addLast("exceutor",
+                    new ExecutorFilter(new UnorderedThreadPoolExecutor(codeThread, maxThread)));
+            int port = this.config.getInt("sgip_mo_port");
+            this.acceptor.bind(new InetSocketAddress(port));
+            log.info("Bind port=" + port);
+        } catch (IOException e) {
+            log.error("", e);
+        }
+    }
+
+    public void dispose() {
+        ExecutorFilter exceutor = (ExecutorFilter) this.acceptor.getFilterChain().get("exceutor");
+        this.acceptor.dispose();
+        if (exceutor != null) {
+            try {
+                Thread.sleep(100L);
+            } catch (InterruptedException e) {
+                log.error("", e);
+            }
+            ThreadPoolExecutor service = (ThreadPoolExecutor) exceutor.getExecutor();
+            service.shutdownNow();
+        }
+        log.info("Disposed!");
+    }
+}

+ 141 - 0
src/main/java/com/nokia/sms/sgip/mo/server/MOServerHandler.java

@@ -0,0 +1,141 @@
+package com.nokia.sms.sgip.mo.server;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.mina.core.future.CloseFuture;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+import com.nokia.sms.sgip.SgipConfig;
+import com.nokia.sms.sgip.message.BindMessage;
+import com.nokia.sms.sgip.message.BindResponseMessage;
+import com.nokia.sms.sgip.message.DeliverMessage;
+import com.nokia.sms.sgip.message.DeliverResponseMessage;
+import com.nokia.sms.sgip.message.Head;
+import com.nokia.sms.sgip.message.ReportMessage;
+import com.nokia.sms.sgip.message.ReportResponseMessage;
+import com.nokia.sms.sgip.message.UnBindMessage;
+import com.nokia.sms.sgip.message.UnBindResponseMessage;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MOServerHandler extends IoHandlerAdapter {
+    private CompositeConfiguration config = SgipConfig.getConfig();
+    private Action deliverAction;
+    private Action reportAction;
+
+    public MOServerHandler() {
+        String deliverActionClass = this.config.getString("sgip_mo_deliver_action_class");
+
+        String reportActionClass = this.config.getString("sgip_mo_report_action_class");
+        try {
+            if ((deliverActionClass != null) && (!"".equals(deliverActionClass))) {
+                Class<?> c1 = Class.forName(deliverActionClass);
+                this.deliverAction = ((Action) c1.newInstance());
+            }
+            if ((reportActionClass != null) && (!"".equals(reportActionClass))) {
+                Class<?> c2 = Class.forName(reportActionClass);
+                this.reportAction = ((Action) c2.newInstance());
+            }
+        } catch (ClassNotFoundException e) {
+            log.info("", e);
+        } catch (InstantiationException e) {
+            log.info("", e);
+        } catch (IllegalAccessException e) {
+            log.info("", e);
+        }
+        if (this.deliverAction != null) {
+            log.info("DeliverActionClass=" + this.deliverAction.getClass());
+        } else {
+            log.warn("DeliverActionClass=null");
+        }
+        if (this.reportAction != null) {
+            log.info("ReportActionClass=" + this.reportAction.getClass());
+        } else {
+            log.warn("ReportActionClass=null");
+        }
+    }
+
+    public void exceptionCaught(IoSession session, Throwable cause)
+            throws Exception {
+        log.error("Remote:" + session.getRemoteAddress(), cause);
+        session.closeOnFlush();
+    }
+
+    public void sessionOpened(IoSession session) {
+        log.info("Remote:" + session.getRemoteAddress());
+    }
+
+    public void sessionClosed(IoSession session, IdleStatus status)
+            throws Exception {
+        log.info("Remote:" + session.getRemoteAddress());
+    }
+
+    public void messageSent(IoSession session, Object object)
+            throws Exception {
+    }
+
+    public void messageReceived(IoSession session, Object object)
+            throws Exception {
+        if ((object instanceof BindMessage)) {
+            BindMessage message = (BindMessage) object;
+            byte operateResult = BindChecker.checkBindMessage(message);
+            BindResponseMessage bindResp = new BindResponseMessage();
+            Head head = new Head();
+            head.setFlowId(message.getHead().getFlowId());
+            bindResp.setHead(head);
+            bindResp.setOperateResult(operateResult);
+            session.write(bindResp);
+            log.info("write:" + bindResp);
+            if (operateResult != 0) {
+                log.warn("CheckBindMessage fail!OperateResult=" + operateResult);
+                CloseFuture closeFuture = session.closeOnFlush();
+                closeFuture.awaitUninterruptibly();
+                log.info("Session closed!" + (!session.isConnected()));
+            }
+        } else if ((object instanceof DeliverMessage)) {
+            DeliverMessage message = (DeliverMessage) object;
+
+            DeliverResponseMessage deliverResp = new DeliverResponseMessage();
+            Head head = new Head();
+            head.setFlowId(message.getHead().getFlowId());
+            deliverResp.setHead(head);
+            deliverResp.setOperateResult((byte) 0);
+            session.write(deliverResp);
+            if (this.deliverAction != null) {
+                this.deliverAction.execute(message);
+            }
+        } else if ((object instanceof ReportMessage)) {
+            ReportMessage message = (ReportMessage) object;
+
+            ReportResponseMessage reportResp = new ReportResponseMessage();
+            Head head = new Head();
+            head.setFlowId(message.getHead().getFlowId());
+            reportResp.setHead(head);
+            reportResp.setOperateResult((byte) 0);
+            session.write(reportResp);
+            if (this.reportAction != null) {
+                this.reportAction.execute(message);
+            }
+        } else if ((object instanceof UnBindMessage)) {
+            UnBindMessage message = (UnBindMessage) object;
+
+            UnBindResponseMessage unBindResp = new UnBindResponseMessage();
+            Head head = new Head();
+            head.setFlowId(message.getHead().getFlowId());
+            unBindResp.setHead(head);
+            session.write(unBindResp);
+
+            CloseFuture closeFuture = session.closeOnFlush();
+            closeFuture.awaitUninterruptibly();
+            log.info("Session closed!" + (!session.isConnected()));
+        }
+    }
+
+    public void sessionIdle(IoSession session, IdleStatus status)
+            throws Exception {
+        session.closeOnFlush();
+        log.info("Closeing!");
+    }
+}

+ 358 - 0
src/main/java/com/nokia/sms/sgip/mt/client/MTClient.java

@@ -0,0 +1,358 @@
+package com.nokia.sms.sgip.mt.client;
+
+import java.io.UnsupportedEncodingException;
+import java.net.InetSocketAddress;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.mina.core.RuntimeIoException;
+import org.apache.mina.core.filterchain.IoFilter;
+import org.apache.mina.core.future.ConnectFuture;
+import org.apache.mina.core.future.WriteFuture;
+import org.apache.mina.core.service.IoConnector;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.logging.LogLevel;
+import org.apache.mina.transport.socket.nio.NioSocketConnector;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.executor.ExecutorFilter;
+import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor;
+
+import com.nokia.sms.sgip.RespCaller;
+import com.nokia.sms.sgip.SgipConfig;
+import com.nokia.sms.sgip.codec.MessageUtil;
+import com.nokia.sms.sgip.codec.SgipCodecFactory;
+import com.nokia.sms.sgip.filter.SGIPLoggingFilter;
+import com.nokia.sms.sgip.message.BindMessage;
+import com.nokia.sms.sgip.message.SubmitMessage;
+import com.nokia.sms.sgip.message.UnBindMessage;
+import com.nokia.sms.sgip.message.SendResult;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MTClient {
+    private IoConnector connector;
+    private CompositeConfiguration config = SgipConfig.getConfig();
+    private static MTClient sgipClient;
+    private static final SimpleDateFormat dateForamt = new SimpleDateFormat("yyMMddHHmmss032+");
+    private IoSession session;
+
+    public static synchronized MTClient getInstance() {
+        if (sgipClient == null) {
+            sgipClient = new MTClient();
+        }
+        return sgipClient;
+    }
+
+    private MTClient() {
+        this.connector = new NioSocketConnector();
+        this.connector.setConnectTimeoutMillis(20000L);
+        this.connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,
+                this.config.getInt("sgip_mt_client_max_idle_time", 50));
+        if (log.isDebugEnabled()) {
+            SGIPLoggingFilter logFilter = new SGIPLoggingFilter("MTClienter");
+
+            logFilter.setExceptionCaughtLogLevel(LogLevel.NONE);
+            logFilter.setSessionCreatedLogLevel(LogLevel.NONE);
+            logFilter.setSessionOpenedLogLevel(LogLevel.NONE);
+            logFilter.setSessionIdleLogLevel(LogLevel.NONE);
+            logFilter.setMessageSentLogLevel(LogLevel.NONE);
+            logFilter.setMessageReceivedLogLevel(LogLevel.DEBUG);
+            logFilter.setSessionClosedLogLevel(LogLevel.NONE);
+            this.connector.getFilterChain().addLast("MTClienter1", logFilter);
+        }
+        IoFilter coderFilter = new ProtocolCodecFilter(new SgipCodecFactory());
+        this.connector.getFilterChain().addLast("coderFilter", coderFilter);
+        this.connector.getFilterChain().addLast("logFilter2", new SGIPLoggingFilter("MTClienter"));
+
+        this.connector.setHandler(new MTClientHandler());
+        ThreadPoolExecutor executor = new UnorderedThreadPoolExecutor(4, 16);
+        this.connector.getFilterChain().addLast("exceutor", new ExecutorFilter(executor));
+
+        MessageUtil.setNodeId((int) this.config.getLong("sgip_mt_node_id"));
+        log.info("Inited!");
+    }
+
+    private synchronized IoSession getSession() {
+        byte connectResult = -1;
+        if ((this.session == null) || (!this.session.isConnected()) || (this.session.isClosing())) {
+            connectResult = connect();
+            if (connectResult != 0) {
+                if (this.session != null) {
+                    this.session.closeOnFlush();
+                }
+                log.warn("Fail to connect!");
+                for (int i = 0; i < 2; i++) {
+                    try {
+                        Thread.sleep(1000L);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    connectResult = connect();
+                    if (connectResult == 0) {
+                        break;
+                    }
+                }
+            }
+            if ((connectResult != 0) &&
+                    (this.session != null)) {
+                this.session.closeOnFlush();
+            }
+        }
+        return this.session;
+    }
+
+    private byte connect() {
+        byte result = -99;
+        String ip = this.config.getString("sgip_mt_server_ip", "127.0.0.1");
+        int port = this.config.getInt("sgip_mt_server_port", 9999);
+        InetSocketAddress address = new InetSocketAddress(ip, port);
+        boolean connectResult = false;
+        try {
+            ConnectFuture connectFuture = this.connector.connect(address);
+            connectResult = connectFuture.awaitUninterruptibly(20L, TimeUnit.SECONDS);
+            if (connectResult) {
+                this.session = connectFuture.getSession();
+
+                BindMessage bind = new BindMessage();
+                bind.setLoginType((byte) 1);
+                bind.setLoginName(SgipConfig.getConfig().getString("sgip_mt_login_name", ""));
+
+                bind.setLoginPassword(SgipConfig.getConfig().getString("sgip_mt_login_password", ""));
+
+                WriteFuture write = this.session.write(bind);
+                write.awaitUninterruptibly();
+                log.info("Write:" + bind);
+                RespCaller caller = new RespCaller();
+                FutureTask<Byte> task = new FutureTask<>(caller);
+                String flowId = bind.getHead().getStrFlowId();
+                this.session.setAttribute("Call" + flowId, caller);
+                this.session.setAttribute("Future" + flowId, task);
+                try {
+                    result = ((Byte) task.get(SgipConfig.getConfig().getLong("submit_time_out", 20L), TimeUnit.SECONDS))
+                            .byteValue();
+                } catch (InterruptedException e) {
+                    this.session.removeAttribute("Call" + flowId);
+                    this.session.removeAttribute("Future" + flowId);
+                    log.error("", e);
+                    if (this.session.isConnected()) {
+                        this.session.closeOnFlush();
+                    }
+                } catch (ExecutionException e) {
+                    this.session.removeAttribute("Call" + flowId);
+                    this.session.removeAttribute("Future" + flowId);
+                    log.error("", e);
+                    if (this.session.isConnected()) {
+                        this.session.closeOnFlush();
+                    }
+                } catch (TimeoutException e) {
+                    this.session.removeAttribute("Call" + flowId);
+                    this.session.removeAttribute("Future" + flowId);
+                    log.error("", e);
+                    result = -2;
+                    if (this.session.isConnected()) {
+                        this.session.closeOnFlush();
+                    }
+                }
+            } else {
+                result = -1;
+                log.warn("Fail to connect:" + address.toString());
+            }
+        } catch (RuntimeIoException e) {
+            log.error(e + address.toString());
+            result = -3;
+            if (this.session.isConnected()) {
+                this.session.closeOnFlush();
+            }
+        }
+        log.debug("result=" + result);
+        return result;
+    }
+
+    public SendResult sendSubmitMsg(SubmitMessage message) {
+        byte result = -99;
+        IoSession session = getSession();
+        if (session == null) {
+            result = -13;
+            log.error("Fail to get session!");
+        } else {
+            session.write(message);
+            log.info("{}", message);
+            RespCaller caller = new RespCaller();
+            FutureTask<Byte> task = new FutureTask<>(caller);
+            String flowId = message.getHead().getStrFlowId();
+            session.setAttribute("Call" + flowId, caller);
+            session.setAttribute("Future" + flowId, task);
+            try {
+                result = ((Byte) task.get(SgipConfig.getConfig().getLong("submit_time_out", 20L), TimeUnit.SECONDS))
+                        .byteValue();
+            } catch (InterruptedException e) {
+                session.removeAttribute("Call" + flowId);
+                session.removeAttribute("Future" + flowId);
+                log.error("", e);
+                if (this.session.isConnected()) {
+                    session.closeOnFlush();
+                }
+            } catch (ExecutionException e) {
+                session.removeAttribute("Call" + flowId);
+                session.removeAttribute("Future" + flowId);
+                log.error("", e);
+                if (this.session.isConnected()) {
+                    session.closeOnFlush();
+                }
+            } catch (TimeoutException e) {
+                session.removeAttribute("Call" + flowId);
+                session.removeAttribute("Future" + flowId);
+                log.error("", e);
+                result = -2;
+                if (this.session.isConnected()) {
+                    session.closeOnFlush();
+                }
+            }
+        }
+        SendResult messageResult = new SendResult(message.getHead().getFlowId(), result);
+
+        log.info("{}", messageResult);
+        return messageResult;
+    }
+
+    public SendResult[] sendMessage(String userNumber, String content) {
+        return sendMessage(null, new String[] { userNumber }, content, null);
+    }
+
+    public SendResult[] sendMessage(String extendPort, String userNumber, String content, Date scheduleTime) {
+        return sendMessage(extendPort, new String[] { userNumber }, content, scheduleTime);
+    }
+
+    public SendResult[] sendMessage(String extendPort, String[] userNumber, String content, Date scheduleTime) {
+        String signature = this.config.getString("sms_signature", null);
+        if ((signature != null) && (!"".equals(signature))) {
+            content = content + signature;
+        }
+        byte[] messageContent = null;
+        try {
+            messageContent = content.getBytes("UnicodeBigUnmarked");
+        } catch (UnsupportedEncodingException e) {
+            log.error("Fail to getByte by UnicodeBigUnmarked!" + e.getMessage());
+        }
+        String strScheduleTime = null;
+        if (scheduleTime != null) {
+            strScheduleTime = dateForamt.format(scheduleTime);
+        }
+        SubmitMessage message = new SubmitMessage();
+        initSumitMessage(message);
+        if (extendPort == null) {
+            message.setSpNumber(this.config.getString("sgip_mt_sp_number"));
+        } else {
+            message.setSpNumber(this.config.getString("sgip_mt_sp_number") + extendPort);
+        }
+        message.setUserCount((byte) userNumber.length);
+        message.setUserNumber(userNumber);
+        message.setScheduleTime(strScheduleTime);
+
+        SendResult[] messageResluts = null;
+        message.setMessageCoding((byte) 8);
+        if (messageContent.length <= 140) {
+            message.setTpudhi((byte) 0);
+            message.setMessageContent(messageContent);
+            messageResluts = new SendResult[] { sendSubmitMsg(message) };
+        } else {
+            message.setTpudhi((byte) 1);
+            byte[][] bytes = MessageUtil.subMessage(messageContent, 140);
+            messageResluts = new SendResult[bytes.length];
+            for (int i = 0; i < bytes.length; i++) {
+                message.setHead(null);
+                message.setMessageContent(bytes[i]);
+                messageResluts[i] = sendSubmitMsg(message);
+            }
+        }
+        return messageResluts;
+    }
+
+    public SendResult[] sendWapush(String extendPort, String userNumber, String url, String content,
+            Date scheduleTime) {
+        return sendWapush(extendPort, new String[] { userNumber }, url, content, scheduleTime);
+    }
+
+    public SendResult[] sendWapush(String extendPort, String[] userNumber, String url, String content,
+            Date scheduleTime) {
+        SubmitMessage message = new SubmitMessage();
+        initSumitMessage(message);
+        if (extendPort == null) {
+            message.setSpNumber(this.config.getString("sgip_mt_sp_number"));
+        } else {
+            message.setSpNumber(this.config.getString("sgip_mt_sp_number") + extendPort);
+        }
+        message.setUserCount((byte) userNumber.length);
+        message.setUserNumber(userNumber);
+        message.setMessageCoding((byte) 4);
+        message.setTpudhi((byte) 1);
+        String strScheduleTime = null;
+        if (scheduleTime != null) {
+            strScheduleTime = dateForamt.format(scheduleTime);
+            message.setScheduleTime(strScheduleTime);
+        }
+        SendResult[] messageResluts = null;
+        try {
+            byte[][] bytes = MessageUtil.buildWAPPush(content, url);
+            messageResluts = new SendResult[bytes.length];
+            for (int i = 0; i < bytes.length; i++) {
+                message.setHead(null);
+                message.setMessageContent(bytes[i]);
+                messageResluts[i] = sendSubmitMsg(message);
+            }
+        } catch (UnsupportedEncodingException e) {
+            log.error("Fail to getByte by UTF-8!" + e.getMessage());
+        }
+        return messageResluts;
+    }
+
+    private void initSumitMessage(SubmitMessage message) {
+        message.setChargeNumber(this.config.getString("sgip_mt_charge_number"));
+        message.setCorpId(this.config.getString("sgip_mt_corp_id"));
+        message.setServiceType(this.config.getString("sgip_mt_service_type"));
+        message.setFeeType(this.config.getByte("sgip_mt_fee_type"));
+        message.setFeeValue(this.config.getString("sgip_mt_fee_value"));
+        message.setGivenValue(this.config.getString("sgip_mt_given_value"));
+        message.setAgentFlag(this.config.getByte("sgip_mt_agen_flag"));
+        message.setMorelatetoMTFlag(this.config.getByte("sgip_mt_morelateto_mt_flag"));
+
+        message.setPriority(this.config.getByte("sgip_mt_priority"));
+        message.setReportFlag(this.config.getByte("sgip_mt_report_flag"));
+        message.setTppid(this.config.getByte("sgip_mt_tppid"));
+        message.setMessageType(this.config.getByte("sgip_mt_message_type"));
+    }
+
+    public void dispose() {
+        ExecutorFilter exceutor = (ExecutorFilter) this.connector.getFilterChain().get("exceutor");
+
+        this.connector.dispose();
+        try {
+            Thread.sleep(100L);
+        } catch (InterruptedException e) {
+            log.error("", e);
+        }
+        if (exceutor != null) {
+            ThreadPoolExecutor service = (ThreadPoolExecutor) exceutor.getExecutor();
+
+            service.shutdownNow();
+        }
+        sgipClient = null;
+        log.info("Disposed!");
+    }
+
+    public void sendUnBindMessage() {
+        getSession().write(new UnBindMessage());
+    }
+
+    public static void main(String[] args)
+            throws UnsupportedEncodingException {
+    }
+}

+ 64 - 0
src/main/java/com/nokia/sms/sgip/mt/client/MTClientHandler.java

@@ -0,0 +1,64 @@
+package com.nokia.sms.sgip.mt.client;
+
+import java.util.concurrent.FutureTask;
+
+import org.apache.mina.core.future.CloseFuture;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+import com.nokia.sms.sgip.RespCaller;
+import com.nokia.sms.sgip.message.SgipMessage;
+import com.nokia.sms.sgip.message.UnBindMessage;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@SuppressWarnings("unchecked")
+public class MTClientHandler extends IoHandlerAdapter {
+    public void sessionOpened(IoSession session) {
+    }
+
+    public void sessionClosed(IoSession session, IdleStatus status)
+            throws Exception {
+    }
+
+    public void messageSent(IoSession session, Object object)
+            throws Exception {
+    }
+
+    public void messageReceived(IoSession session, Object object)
+            throws Exception {
+        SgipMessage message = (SgipMessage) object;
+        if (message.getHead().getCommandId() == -2147483646) {
+            try {
+                CloseFuture closeFuture = session.closeOnFlush();
+                closeFuture.awaitUninterruptibly();
+            } catch (Exception e) {
+                log.error("", e);
+            }
+            log.info("Session closed!" + (!session.isConnected()) + ",id=" + session.getId());
+            return;
+        }
+        String flowId = message.getHead().getStrFlowId();
+        RespCaller caller = (RespCaller) session.removeAttribute("Call" + flowId);
+        if (caller == null) {
+            Thread.sleep(100L);
+            caller = (RespCaller) session.removeAttribute("Call" + flowId);
+        }
+        FutureTask<Byte> task = (FutureTask<Byte>) session.removeAttribute("Future" + flowId);
+        if ((caller != null) && (task != null)) {
+            caller.setRespMessage(message);
+            task.run();
+        } else {
+            log.warn("Fail to get caller." + message);
+        }
+    }
+
+    public void sessionIdle(IoSession session, IdleStatus status)
+            throws Exception {
+        UnBindMessage unBind = new UnBindMessage();
+        session.write(unBind);
+        log.info("Write:" + unBind + ",id=" + session.getId());
+    }
+}

+ 35 - 0
src/main/java/com/nokia/sms/sgip/servlet/MOServerServlet.java

@@ -0,0 +1,35 @@
+package com.nokia.sms.sgip.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import com.nokia.sms.sgip.mo.server.MOServer;
+
+public class MOServerServlet implements Servlet {
+    
+    public void destroy() {
+        MOServer.getInstance().dispose();
+    }
+
+    public ServletConfig getServletConfig() {
+        return null;
+    }
+
+    public String getServletInfo() {
+        return null;
+    }
+
+    public void init(ServletConfig arg0)
+            throws ServletException {
+        MOServer.getInstance();
+    }
+
+    public void service(ServletRequest arg0, ServletResponse arg1)
+            throws ServletException, IOException {
+    }
+}

+ 72 - 0
src/main/resources/sgipConfig.properties

@@ -0,0 +1,72 @@
+#=======与网关的连接配置信息========
+# 网关ip
+sgip_mt_server_ip=133.96.90.123
+# 网关端口
+sgip_mt_server_port=8801
+# 连接最大空闲时间,建议值50
+sgip_mt_client_max_idle_time=50
+# 发送下行消息等待响应最长时间建议值20
+sgip_mt_received_time_out=20
+#======与网关的连接配置信息结束======
+
+#\u4E0B\u884C\u77ED\u4FE1\u7684\u7B7E\u540D(\u53EF\u5305\u542B\u7A7A\u683C),\u5982\u914D\u7F6E\u4E3Asgip_mt_message_signature=--\u5E7F\u4E1C\u8054\u901A\uFF0C\u5219\u4E0B\u53D1\u7684\u77ED\u4FE1\u4F1A\u662F\uFF1A\u201C\u6D4B\u8BD5\u77ED\u4FE1 --\u5E7F\u4E1C\u8054\u901A\u201D\u3002\u7559\u7A7A\u5219\u4E0D\u6DFB\u52A0\u7B7E\u540D
+# 使用这个配置必须配置文件为UTF-8编码
+sms_signature=
+
+#========下行消息参数配置,具体请参考sgip协议========
+# 从sgip_mt_charge_number到sgip_mt_message_type在不清楚含义的情况下不要随意修改
+
+# 网关分配给sp的节点号
+sgip_mt_node_id=14362
+# sp作为客户绑定网关时的用户名 
+sgip_mt_login_name=14362
+# sp作为客户绑定网关时的密码
+sgip_mt_login_password=ZXwg20@@
+# 网关分配给sp的主端口号
+sgip_mt_sp_number=1065577000
+# 企业代码
+sgip_mt_corp_id=14362
+#\u4ED8\u8D39\u53F7\u7801
+# 付费号码
+sgip_mt_charge_number=000000000000000000000
+# 业务代码
+sgip_mt_service_type=ffff
+# 计费类型
+sgip_mt_fee_type=1
+# 该条短消息的收费值,单位为分
+sgip_mt_fee_value=0
+# 赠送用户的话费,单位为分
+sgip_mt_given_value=0
+# 代收费标志  0 应收, 1 实收
+sgip_mt_agen_flag=1
+# 引起MT消息的原因
+sgip_mt_morelateto_mt_flag=0
+# 优先级 0-9 由低到高 默认为0
+sgip_mt_priority=0
+# 状态报告标记
+sgip_mt_report_flag=1
+# gsm协议类型
+sgip_mt_tppid=0
+# 信息类型 0 短消息
+sgip_mt_message_type=0
+#========下行消息配置结束========
+
+#========用于接受网关的消息的服务端相关配置=====
+# 本地监听的MO消息的端口
+sgip_mo_port=8802
+# 提供给网关登录时的用户名
+sgip_mo_login_name=123
+# 提供给网关登录时的密码
+sgip_mo_login_password=123
+
+# 处理网关发过来的消息的连接池初始化线程数
+sgip_mo_threadpool_code_thread=4
+# 处理网关发过来的消息的连接池最大线程数
+sgip_mo_threadpool_max_thread=16
+# 与网关的socket连接的超时时间
+sgip_mo_socket_timeout=5
+# 处理上行消息的类
+sgip_mo_deliver_action_class=com.nokia.sms.action.DeliverAction
+# 处理下行消息的类
+sgip_mo_report_action_class=com.nokia.sms.action.ReportAction
+#=======用于接收网关的消息的服务端相关配置结束======

+ 19 - 0
src/test/com/nokia/sms/service/SmsServiceTest.java

@@ -0,0 +1,19 @@
+package com.nokia.sms.service;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import com.nokia.sms.pojo.Sms;
+
+@SpringBootTest
+public class SmsServiceTest {
+    @Autowired
+    private SmsService service;
+
+    @Test
+    public void test() {
+        boolean b = service.sendMessage(new Sms());
+        System.out.println(b);
+    }
+}

+ 3 - 1
短信网关接口说明.md

@@ -5,6 +5,7 @@ fromSystem  来源系统,按照约定传固定值 如 tousuliucheng
 phone 手机号
 message  短信内容文本
 messageType  各系统自行定义的消息类型,仅用于记录
+internalId  系统内编号,可以考虑群发使用相同编号
 
 ```http
 http://192.168.70.125:12080/api/sms/send
@@ -14,7 +15,8 @@ Content-Type: application/json
   "fromSystem": "tousuliucheng",
   "phone": "13231899751",
   "message": "这是一条短信",
-  "messageType": "催单"
+  "messageType": "催单",
+  "internalId": "内部编号"
 }
 ```