📄 spsmsservice.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 + -