总结&备忘:smslib&长短信

来源:互联网 发布:斐波那契java 编辑:程序博客网 时间:2024/06/05 10:32

背景:

       项目中使用了开源库smslib-3.5.4与GSM-Modem通信实现短信收发(包括使用长短信)。使用中发现该开源库对长短信的处理存在BUG,如:

       1、当长短信的REF值为0时,会当作是普通单条短信,不作拼接;

       2、当收到多个手机端过来的长短信时,拼接内容会乱,或接收不到部分短信,或手机卡短信塞满;


原因:

       1、org.smslib.modem.ModemGateway.readMessagesPDU()中判断是否为长短信息使用了如下逻辑:

if (msg.getMpRefNo() == 0){  // single message  msgList.add(msg);  incInboundMessageCount();}else{  // multi-part message  ...}

              因为在标准(《GSM 03.40 V7.2.0》 “9.2.3.24.1 Concatenated Short Messages”)里REF的值的取值范围为[0,255],故此处按REF值为0来判断是单条短信是错误的;

       2、org.smslib.modem.ModemGateway.readMessagesPDU()中判断长短信分块是否属于同一长短信时使用了如下逻辑:

// check if current message list is for this messageif (listMsg.getMpRefNo() == msg.getMpRefNo())

              这逻辑只根据短信的REF值相同就认为是属于同一长短信,这是不合理的,因为这个REF值是发送方自己选择的,当多个发送端时,很有可能存在某些发送端同时选择了同一个REF值作为它们所发长短信的REF值,服务端此时接收到这些长短信时,若按上述原逻辑,则会认为这些不同发送端过来的长短信分块都是同一长短信的分块,最后导致同分块号的分块拼接到其他发送者,或不被处理(进而产生孤儿短信)


解决:

       1、修改该逻辑源码为:

if (msg.getMpMaxNo() == 0){  // single message  msgList.add(msg);  incInboundMessageCount();}else{  // multi-part message  ...}

       2、修改该逻辑源码为:

// check if current message list is for this messageif (listMsg.getMpRefNo() == msg.getMpRefNo() && listMsg.getMpMaxNo() == msg.getMpMaxNo() && listMsg.getOriginator().equals(msg.getOriginator()) && (distanceOfDate(listMsg.getDate(), msg.getDate()) < 1000*60*30))

              该逻辑加入了分块必须满足以下条件才认为是属于同一长短信:

              1) 标识值相等;

              2) 总分块数相等;

              3) 发送者相同;

              4) 发送时间间隔不超过30秒(这个可以根据自己的场景定义分块间最大间隔时间)



0 0
原创粉丝点击