用Java实现PDU编码

PDU编码的方案网上很多,可以参考一下,我们只要按照协议格式去做就行了。要注意的一点是短消息内容需要进行Unicode编码转换。

1.发英文

 发英文时可以进行7bit编码或8bit编码.因为英文和数字等小于128的Ascii码,高位为0,所以,我们可以把最高位也利用起来,去掉最高位的0,然后,每个字节的位以次向前移动,这样一条短信就可以发最多160个字符。因为GSM协议规定短信最多是140个字节,这样的话总共是140×8=1120位,如果我们每个字节只占7位的话,那么就可以容下:1120/7=160个字符。

当然也可以用UCS2(也就是UTF-16,每个字符占两个字节),这样的话,发送只能发送最多有70个英文字符

2.发中文

发送中文时,必须用UCS2进行编码,最多可以发140/2=70个汉字。

接收到短消息之后,按编码方式进行解码就行了。

3.参考源代码:

 

package  com.gftech.common;

public   class  PduPack  {
 
// 短消息中心号长度
 private String smscLen;

 
private String smscFormat;

 
// 短消息中心号
 private String smsc;

 
// 源地址长度
 private int addrLen;

 
private String addrFormat;

 
// 源地址
 private String addr;

 
// 短消息内容编码方式,tp_dcs
 private String msgCoding;

 
// 时间戳,tp_scts
 
// private String timestamp;
 
 
private int msgLen;

 
// 短消息内容,tp_ud
 private String msgContent;

 
public PduPack() {
  smscLen 
= "08";
  smscFormat 
= "91";
  addrLen 
= 13;
  addrFormat 
= "91";

 }


 
public PduPack(String src) {

  
if (src != null && src.length() > 44{
   String temp 
= src.substring(418);
   smsc 
= GFString.interChange(temp);
   
if (smsc != null && smsc.length() > 1){
    smsc 
= smsc.substring(0, smsc.length() - 1);
    
if(smsc.length()==13)
     smsc
=smsc.substring(2);
   }


   temp 
= src.substring(2022);
   addrLen 
= Integer.parseInt(temp, 16);
   
if (addrLen % 2 == 0)
    temp 
= src.substring(2424 + addrLen);
   
else
    temp 
= src.substring(2424 + addrLen + 1);
   addr 
= GFString.interChange(temp);
   
// 去掉为补齐为偶数加上的那一位
   if (addr != null && addr.length() % 2 == 0{
    addr 
= addr.substring(0, addr.length() - 1);
    
if (addr.length() == 13)// 如果前面有86,去掉它
     addr = addr.substring(2);
   }

   
if (addrLen % 2 == 0{
    msgCoding 
= src.substring(24 + addrLen + 224 + addrLen + 4);
    temp 
= src.substring(24 + addrLen + 4 + 16);
   }
 else {
    msgCoding 
= src.substring(24 + addrLen + 324 + addrLen + 5);
    temp 
= src.substring(24 + addrLen + 5 + 16);
   }

   
if (msgCoding.equals("08"))
    msgContent 
= GFString.unicode2gb(temp);
   
else
    msgContent 
= GFString.decode7bit(temp);

  }

 }


 
public void setSmsc(String s) {
  
if (s != null{
   String centerNo 
= null;
   
if (s.length() == 11 && s.substring(02).equals("13")) {
    centerNo 
= "86" + s;
   }
 else if (s.length() == 13
     
&& s.substring(04).equals("8613")) {
    centerNo 
= s;
   }
 else if (s.length() == 14
     
&& s.substring(05).equals("+8613")) {
    centerNo 
= s.substring(1);
   }
 else
    
return;

   
this.smsc= GFString.interChange(centerNo);
  }

 }


 
public void setAddr(String ad) {
  
if (ad != null{
   String centerNo 
= null;
   
if (ad.length() == 11 && ad.substring(02).equals("13")) {
    centerNo 
= "86" + ad;
   }
 else if (ad.length() == 13 && ad.substring(04).equals("8613")) {
    centerNo 
= ad;
   }
 else if (ad.length() == 14 && ad.substring(05).equals("+8613")) {
    centerNo 
= ad.substring(1);
   }
 else if (ad.length() > 0{// 特服号
    addrFormat = "A1";
    addrLen 
= ad.length();
    centerNo 
= ad;
   }
 else
    
return;

   addr 
= GFString.interChange(centerNo);
  }

 }


 
/**
  * 设置编码方式
  * 
  * 
@param encoding
  *            0:表示7-BIT编码 4:表示8-BIT编码 8:表示UCS2编码
  
*/

 
public void setMsgCoding(int encoding) {
  
if (encoding == 8)
   msgCoding 
= "08";
  
else if (encoding == 4)
   msgCoding 
= "04";
  
else
   msgCoding 
= "00";

 }


 
/**
  * 短消息内容
  * 
  * 
@param content
  
*/

 
public void setMsgContent(String content) {
  
if (content != null{
   
if (content.length() == content.getBytes().length) {
    msgCoding 
= "00";
    msgLen 
= content.getBytes().length;
    msgContent 
= encode7bit(content);
     
   }
 else {
    msgCoding 
= "08"
    msgContent 
= GFString.gb2unicode(content);
    
if(msgContent!=null
     msgLen
=msgContent.length()/2;
     
   }

   
   
if(msgContent!=null){
    msgContent
=msgContent.toUpperCase();
    
   }

  }

 }


 
/**
  * 
  * 
@return 经过PDU编码的结果,十六进制字符串形式
  
*/

 
public String getCodedResult() {
  String result 
= null;
  
final String tp_mti = "11";
  
final String tp_mr = "00";
  
final String tp_pid = "00";
  
final String tp_vp = "00";

  
if (smsc != null && addr != null && msgContent != null{
   result 
= smscLen + smscFormat + smsc + tp_mti + tp_mr
     
+ GFString.byte2hex((byte) addrLen) + addrFormat + addr
     
+ tp_pid + msgCoding + tp_vp
     
+ GFString.byte2hex((byte) msgLen) + msgContent;
   result 
= result.toUpperCase();
  }


  
return result;
 }


 
public String getAddr() {
  
return addr;
 }


 
public String getMsgCoding() {
  
return msgCoding;
 }


 
public String getMsgContent() {
  
return msgContent;
 }


 
public int getMsgLen() {
  
return msgLen;
 }


 
public String getSmsc() {
  
return smsc;
 }


 
//TODO:temp
 public static String encode7bit(String src) {
  String result 
= null;
  String hex 
= null;
  
byte value;

  
if (src != null && src.length() == src.getBytes().length) {
   result 
= "";
   
byte left=0;
   
byte[] b = src.getBytes();
   
for (int i = 0, j = 0; i < b.length; i++{
    j 
=& 7;
    
if (j == 0)
     left 
= b[i];
    
else {
     value 
=(byte)((b[i] << (8 - j))|left);
     left
=(byte)(b[i]>>j);
     hex 
= GFString.byte2hex((byte) value);
     result 
+= hex;
     
if(i==b.length -1)
      result
+=GFString.byte2hex(left);
    }

   }

   
   result
=result.toUpperCase();
  }

  
return result;
 }

}



/**
  * 7-BIT编码 把ASCII码值最高位为0的字符串进行压缩转换成8位二进制表示的字符串
  * 
  * 
@param src
  * 
@return
  
*/

 
public   static  String encode7bit(String src)  {
  String result 
= null;
  String hex 
= null;
  
byte value;

  
if (src != null && src.length() == src.getBytes().length) {
   result 
= "";
   
byte left=0;
   
byte[] b = src.getBytes();
   
for (int i = 0, j = 0; i < b.length; i++{
    j 
=& 7;
    
if (j == 0)
     left 
= b[i];
    
else {
     value 
=(byte)((b[i] << (8 - j))|left);
     left
=(byte)(b[i]>>j);
     hex 
= GFString.byte2hex((byte) value);
     result 
+= hex;
     
if(i==b.length -1)
      result
+=GFString.byte2hex(left);
    }

   }

   
   result
=result.toUpperCase();
  }

  
return result;
 }

    
 
/**
  * 对7-BIT编码进行解码
  * 
@param src 十六进制的字符串,且为偶数个
  * 
@return 源字符串
  
*/

 
public   static  String decode7bit(String src)  {
  String result 
= null;
        
int[] b;
        String temp
=null;
        
byte srcAscii;
        
byte left=0;
        
  
if (src != null && src.length() %2==0{
   result
="";
           b
=new int[src.length() /2];
           temp
=src+"0";
           
for(int i=0,j=0,k=0;i<temp.length() -2;i+=2,j++){
             b[j]
=Integer.parseInt(temp.substring(i,i+2),16);
             
             k
=% 7;
             srcAscii
=(byte)(((b[j]<<k) & 0x7F)|left);
             result
+=(char)srcAscii;
             left
=(byte)(b[j]>>>(7-k));
             
if(k==6){
              result
+=(char)left;
              left
=0;
             }

             
if(j==src.length() /2)
              result
+=(char)left;
           }

  }

  
return result;
 }



/**
  * 把UNICODE编码的字符串转化成汉字编码的字符串
  * 
  * 
@param hexString
  * 
@return
  
*/

 
public   static  String unicode2gb(String hexString)  {
  StringBuffer sb 
= new StringBuffer();

  
if (hexString == null)
   
return null

  
for (int i = 0; i + 4 <= hexString.length(); i = i + 4{
   
try {
    
int j = Integer.parseInt(hexString.substring(i, i + 4), 16);
    sb.append((
char) j);
   }
 catch (NumberFormatException e) {
    
return hexString;
   }

  }


  
return sb.toString();
 }


 
/**
  * 把汉字转化成UNICODE编码的字符串
  * 
  * 
@param gbString
  * 
@return
  
*/

 
public   static  String gb2unicode(String gbString)  {
  String result 
= "";
  
char[] c;
  
int value;

  
if (gbString == null)
   
return null;
  
// if (gbString.getBytes().length == gbString.length())
  
// return gbString;

  String temp 
= null;
  c 
= new char[gbString.length()];
  StringBuffer sb 
= new StringBuffer(gbString);
  sb.getChars(
0, sb.length(), c, 0);
  
for (int i = 0; i < c.length; i++{
   value 
= (int) c[i];
   
// System.out.println("[" + i + "]:" +value );
   
// System.out.println("hex:"+Integer.toHexString(value));
   temp = Integer.toHexString(value);
   result 
+= fill(temp, 4);
  }


  
return result.toUpperCase();
 }



4.结束语

上面的源代码可能并不十分完整,但最重要的部分都有了。做为大家学习考参的例子。

PDU编码的详细介绍,请参考下面的参考资料

5.参考资料

bhw98的专栏 ttp://blog.csdn.net/bhw98/archive/2003/03/27/19666.aspx

你可能感兴趣的:(JAVA)