⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spsmsservice.java

📁 采用JAVA开发
💻 JAVA
字号:
package com.gctech.sms.sp;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;

import EDU.oswego.cs.dl.util.concurrent.Sync;

import com.gctech.sms.dao.SpLoginInfoDao;
import com.gctech.sms.msg.MTAck;
import com.gctech.sms.msg.MTInfo;
import com.gctech.sms.msg.StructConverter;
import com.gctech.sms.platform.MTDispatcher;
import com.gctech.sms.sp.msg.MsgHead;
import com.gctech.sms.sp.msg.SubscribeResp;
import com.gctech.sms.sp.msg.UnsubscribeResp;
import com.gctech.sms.util.ThreadManager;
import com.gctech.sms.vo.SpLoginInfo;
import com.gctech.util.MD5;
import com.gctech.util.Tools;
import com.gctech.util.net.SocketService;

/**
 * <p>Title: 给SP提供的短信服务器</p>
 * <p>Description: 给SP提供的短信服务器,需要认证。</p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: gctech</p>
 * @author 王红宝
 * @version $Id: SpSmsService.java,v 1.4 2004/07/09 08:06:38 wengjl Exp $
 */

public class SpSmsService extends SocketService{

  public SpSmsService(){
    super();
    mtSendOut = new Vector();
  }
  OutputStream out;
  private String spId;
  private List mtSendOut;

  static final int SUCESS = 0;
  static final int ERROR_DATA_LENGTH = 1;
  static final int WRONG_CLIENT_IP = 2;
  static final int MD5_ERROR = 3;
  static final int SP_NOT_FOUND = 4;
  //超时时间,3分钟
  static final int TIME_OUT = 3*60*1000;

  /**
   * 订阅应答。
   * */
  void subscribResp(byte[] subscribResp){
    String msgId = new String(subscribResp, 12, 20).trim();
    SubscribeResp resp = new SubscribeResp();
    resp.setMsgId(msgId);
    MsgHead head = new MsgHead();
    head.setCommandStatus(Tools.byte2int(subscribResp, 4));
    resp.setMsgHead(head);
    SpServer server = SpServer.getInstance();
    Object obj = server.putSubscribeResp(msgId, resp);
    if ( obj instanceof Sync ){
      Sync lock = (Sync)obj;
      //解锁
      lock.release();
    }else{
      logger.warn(obj);
      server.removeSubResp(msgId);
    }
  }

  /**
   * 退订应答。
   * */
  void unsubscribResp(byte[] unsubscribResp){
    String msgId = new String(unsubscribResp, 12, 20).trim();
    UnsubscribeResp resp = new UnsubscribeResp();
    resp.setMsgId(msgId);
    MsgHead head = new MsgHead();
    head.setCommandStatus(Tools.byte2int(unsubscribResp, 4));
    resp.setMsgHead(head);
    logger.debug(resp);
    SpServer server = SpServer.getInstance();
    Object obj = server.putUnsubscribeResp(msgId, resp);
    if ( obj instanceof Sync ){
      Sync lock = (Sync)obj;
      //解锁
      lock.release();
    }else{
      logger.warn(obj);
      server.removeSubResp(msgId);
    }

  }

  /***
   * 下行消息。
   * */
  void submit(byte[] submitReq) {
    logger.debug(new String(submitReq));
    try {
      String theSpId = new String(submitReq, 12, 20).trim();
      if ( spId.equals(theSpId) ){
        //启动线程分拣下行短信。
        SubmitTask task = new SubmitTask(submitReq, out);
        ThreadManager.getInstance().execute(task);
      }else{
        //SP ID和登录的不相同
        logger.warn("the spId are not equal!");
      }
    }
    catch (InterruptedException ex) {
      logger.error(ex, ex);
    }
  }

  /**
   * 退出回应。
   * */
  void exitResp(byte[] exitReq) throws IOException {
    byte[] exitResp = new byte[16];
    Tools.int2byte(16, exitResp, 0);
    Tools.int2byte(Constants.EXIT_RES, exitResp, 4);
    System.arraycopy(exitReq, 8, exitResp, 12, 4);
    send(exitResp);
    sock.close();
  }

  /**
   * 检测消息回复。
   * */
  void activeTestResp(byte[] activeTest) throws IOException {
    byte[] activeResp = new byte[16];
    Tools.int2byte(16, activeResp, 0);
    Tools.int2byte(Constants.ACTIVE_TEST_RES, activeResp, 4);
    System.arraycopy(activeTest, 8, activeResp, 12, 4);
    send(activeResp);
  }
  synchronized void send(byte[] data) throws IOException {
    int cmdId = Tools.byte2int(data, 4);
    System.out.println(cmdId);
    System.out.println("spip="+sock.getInetAddress().getHostAddress());
    //System.out.println("port=" + sock.getPort());
    out.write(data);
  }

  //运行服务
  void doService() throws IOException {
    while( sock != null && sock.isConnected() ){
      //读消息头
      DataInputStream in = new DataInputStream(sock.getInputStream());
      //读取长度
      int msgLength = in.readInt();
      logger.debug("receive msgSize is:" + msgLength);
      //正确的消息
      if ( msgLength >= 16 && msgLength <= 2048 ){
        //读取数据
        byte[] resp = new byte[msgLength-4];
        in.read(resp);
        //处理数据
        int cmdId = Tools.byte2int(resp);
        switch ( cmdId ){
          //检测消息
          case Constants.ACTIVE_TEST_REQ:
            activeTestResp(resp);
            break;
          //退出消息
          case Constants.EXIT_REQ:
            exitResp(resp);
            break;
          //下行短信消息
          case Constants.SUBMIT_REQ:
            //异步发送消息。
            submit(resp);
            break;
          //订阅应答
          case Constants.SUBSCRIBE_RES:
            subscribResp(resp);
            break;
          //退订应答
          case Constants.UNSUBSCRIBE_RES:
            unsubscribResp(resp);
            break;
          default:
            logger.warn("can't found the cmdId:"+cmdId);
            break;
        }
      }else{
        throw new IOException("data length error:"+msgLength);
      }
    }
  }


  public static void main(String[] args) {
    System.out.println("192.168.171.31".matches(".*"));
    System.out.println("192.168.171.31".matches("192.168.171.31"));
    System.out.println("192.168.171.31".matches("192.168.171.4324"));
  }
  public void run(){
    spId = "UNKNOW";
    String clientIp = "UNKNOW";
    try{
      sock.setSoTimeout(TIME_OUT);
      int status = SUCESS;
      byte[] authSvr = null;
      //获取client ip
      clientIp = sock.getInetAddress().getHostAddress();
      //此处接收一个登录信息
      InputStream in = sock.getInputStream();
      byte[] data = new byte[Constants.LOGIN_MSG_LENGTH];
      int rt = in.read(data);
      if ( rt != Constants.LOGIN_MSG_LENGTH ){
        logger.warn("从"+clientIp+"的连接包数据长度错误"+rt);
        status = ERROR_DATA_LENGTH;
      }else{
        //取出spId
        spId = new String(data, 16, 20).trim();
        //查询出SP信息。
        SpLoginInfo login = SpLoginInfoDao.findByPk(spId);
        if ( login == null ){
          logger.warn("不能找到 "+ spId + " 登录信息!");
          status = SP_NOT_FOUND;
          //
        //}else if (login.getClientIp().equals(clientIp)) {
        }else if ( clientIp.matches(login.getClientIp()) ) {
          //取出时间戳
          String timestamp = "" + Tools.byte2int(data, 52);
          if ( timestamp.length() < 10 ){
            timestamp = "0" + timestamp;
          }
          logger.debug(timestamp);
          //计算明文长度
          int plainLen = 20 + 7 +
              login.getSharedSecret().getBytes().length + 10;
          logger.debug("plainLen:"+plainLen);
          byte[] plain = new byte[plainLen];
          //拼凑明文
          System.arraycopy(data, 16, plain, 0, 20);
          byte[] temp = login.getSharedSecret().getBytes();
          System.arraycopy(temp, 0, plain, 27, temp.length);
          int start = 27+temp.length;

          temp = timestamp.getBytes();
          logger.debug("temp:"+temp.length);
          logger.debug("start:"+start);
          System.arraycopy(temp, 0, plain, start, 10);
          logger.debug("plain:"+new String(plain));
          //MD5
          MD5 md5 = new MD5() ;
          byte[] md5Msg = md5.getMD5ofBytes(plain, plain.length);
          //short dddd = md5Msg[16];
          //logger.debug("ddddd " +dddd);
          //校验md5
          boolean authen = true;
          for ( int i = 0; i < 16; i++ ){
            if ( md5Msg[i] == data[36+i] ){
            }else{
              authen = false;
              break;
            }
          }
          String authenClient = new String(data, 36, 16);
          //int a1 = Tools.byte2int(data,36);
          /*for (int i = 0;i<16;i++){
            short ddd = data[36+i];
            logger.debug("ddd"+i+" " + ddd);
          }*/

          if ( authen ){
            //生成server端MD5
            //程序修改2004-7-2 wjl
             byte[] svrPlain= new byte[(status + authenClient + login.getSharedSecret()).getBytes().length];
            //byte[] svrPlain = (status + authenClient + login.getSharedSecret()).getBytes();
            //byte[] svrPlain = (authenClient).getBytes();
            Tools.int2byte(status,svrPlain,SUCESS);
            System.arraycopy(data,36,svrPlain,1,16);
            temp = login.getSharedSecret().getBytes();
            System.arraycopy(temp,0,svrPlain,17,temp.length);
            logger.debug("生成server端MD5 " +status + authenClient + login.getSharedSecret());

            authSvr = md5.getMD5ofBytes(
                svrPlain, svrPlain.length);
            //authSvr = svrPlain;
            /*for (int i = 0;i<svrPlain.length;i++){
              short ddd = svrPlain[i];
              logger.debug("eeee"+i+" " + ddd);
            }*/
            logger.debug("authSvr " + new String(authSvr));
          }else{
            logger.debug(authenClient +" VS "+ new String(md5Msg));
            status = this.MD5_ERROR;
          }
        }else {
          logger.warn("SP " + spId + " 从" + clientIp + "发过来的请求错误,正确的IP应该是:"
                      + login.getClientIp());
          status = WRONG_CLIENT_IP;
        }
      }
      //回复消息
      out = sock.getOutputStream();
      byte[] loginResp = new byte[32];
      Tools.int2byte(32, loginResp, 0);
      Tools.int2byte(Constants.LOGIN_RES, loginResp, 4);
      Tools.int2byte(status, loginResp, 8);
      //复制序列号
      System.arraycopy(data, 12, loginResp, 12, 4);
      if ( status == this.SUCESS ){
        System.arraycopy(authSvr, 0, loginResp, 16, 16);
        System.out.println("onwser spip="+sock.getInetAddress().getHostAddress());
        out.write(loginResp);
        SpServer.getInstance().register(this);
        logger.info( " Register "+spId+" from "+clientIp+"\t\t\t\t\t\t[OK]" );
        doService();
      }else{
        logger.debug("status:" + status);
        out.write(loginResp);
        sock.close();
        sock = null;
      }
    } catch( Throwable e ){
      logger.error(e, e);
    } finally{
      if ( sock != null ){
        try{
          sock.close();
        }
        catch (Throwable ex) {
          logger.error(ex, ex);
        }
        sock = null;
      }
      SpServer.getInstance().unregister(this);
      logger.info("释放从"+spId+":"+clientIp+"过来的连接 \t\t\t\t\t\t[成功]" ) ;
    }
  }
  public String getSpId() {
    return spId;
  }

  static final Logger logger = Logger.getLogger(SpSmsService.class);
}

class SubmitTask implements Runnable{
  byte[] submitReq;
  OutputStream out;
  public SubmitTask(byte[] submitReq, OutputStream out){
    this.submitReq = submitReq;
    this.out = out;
  }
  public void run() {
    //组织消息
    MTInfo info = StructConverter.structToMt(submitReq);
    //增加到发送列表
    MTAck ack = MTDispatcher.getInstance().dispatch(info);
    //写回数据
    try {
      byte[] data = new byte[36];
      Tools.int2byte(36, data, 0);
      Tools.int2byte(Constants.SUBMIT_RES, data, 4);
      Tools.int2byte(ack.getStatus(), data, 8);
      System.arraycopy(submitReq, 8, data, 12, 4);
      if ( ack.getStatus() == 0 ){
        byte[] msgId = ack.msgId.getBytes();
        System.arraycopy(msgId, 0, data, 16, msgId.length);
      }
      out.write(data);
    }
    catch (IOException ex) {
      ex.printStackTrace();
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -