现在是我们的程序做SMPP的服务器,网关连接我方。在连接成功,并BIND后。我方用OUTPUTSTREAM数据流格式向网关发送短消息后,(强制使线程等待了10秒)手机已经接到短消息。但我使用BIND链路的INPUTSTREAM去接收返回状态的数据,竟然出现Connection Reset的错误。
估计原因是OUTPUTSTREAM的阻塞状态仍未结束。(但我信息明明已经发完了,手机都已经收到了)
请问 这是怎么回事啊?改如何解决啊。都已经郁闷好几天了。
另外请问下 该如何监听socket的阻塞状态啊?穷人,求求大家帮帮忙吧

解决方案 »

  1.   

    主要代码如下 请大家帮忙给看下 为什么出错啊 各位大哥行行好吧public class SmppSendMess{byte[] read(int i) throws IOException{
    int j = 0;
    byte abyte0[] = new byte[i];
    try {
    int k;
    for (; j < i; j += k)
    if ((k = in.read(abyte0, j, i - j)) == -1)////出错 Connection Reset
    throw new IOException("SMSC Connection closed (remotely)");
    return abyte0;
    } catch (IOException ioexception) {
    log("Read error " + ioexception.getMessage());
    throw ioexception;
    }

    }public smppHeader getSendResult(){
    smppHeader smppheader=null;
    try {
    byte[] ir=null;
    ir=read(16);//出错 Connection Reset
    log.info("返回消息=="+new String(ir));
    In_ReadToString irt=new In_ReadToString(ir);
    PDUHeader pdu=irt.getSmppHeader();
    smppheader=new smppHeader();
    smppheader.command=pdu.getCommandId();
    smppheader.length=pdu.getCommandLength();
    smppheader.sequence=pdu.getSequenceNumber();
    smppheader.status=pdu.getCommandStatus();
    } catch (decoderException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    //getSendResult();
    closed();
    e.printStackTrace();
    }finally{
    return smppheader;
    }

    } public void sendMessages(Message message) throws Exception {
    smppEncoder smppencoder1 = new smppEncoder();
    smppencoder1.submit(message);
    smppHeader smppheader = new smppHeader();
    log.info("发送信息:"+message.DubugtoString());
    smppheader.command = 5;
    smppheader.sequence = message.seq;
    smppheader.status = 0;
    smppheader.length = 16 + smppencoder1.getBytes().length;
    smppEncoder smppencoder = new smppEncoder();
    smppencoder.smppHeader(smppheader);
    log("isBound="+s.isBound());
    //DataOutputStream pout=new DataOutputStream(out);
    out.write(smppencoder.getBytes(),0,16);
    out.write(smppencoder1.getBytes(),0,smppencoder1.getBytes().length);
    log("length1="+smppencoder.getBytes().length);//16
    log("length2="+smppencoder1.getBytes().length);//109
    out.flush(); //信息不会立即发送完 可能是字节比较多 字节编码方式是UCS2
    //out.close();
    //s.close();
    log("send message"+message.seq);

    }        public SmppSendMess(int i) throws Exception {
    ss = new ServerSocket(i);
    this.log = Appmain.getLog(); } public boolean start() throws Exception {
    boolean flag = false;
    int i = 0x989680;
    log("Started, ready to accept");

    do {

    flag=false;
    s = ss.accept();
    s.setKeepAlive(true);
    s.setTcpNoDelay(true);
    log.info("客户端地址==" + s.getInetAddress().getHostAddress());
    out = s.getOutputStream();
    in = s.getInputStream();//省略了下面的业务判断
                            flag=TRUE;
                          }WHILE(!flag)
                          return flag;         }
             
             public static void main(String[] args){                                        SmppSendMess smppSubmit = new SmppSendMess(5018);
    boolean isc=false;
    while(!isc){
    isc=smppSubmit.start();
    }
    int count=0;
    getSendMess getmess = new getSendMess();
    sendList = getmess.getMess();
    for(int i=0;i<sendList.size();i++){
    Message mess=(Message) sendList.get(i);
    smppSubmit.sendMessages(mess);
    sleep(10000);
    this.wait(10000);
    smppHeader sh = smppSubmit.getSendResult();
    if (sh != null) {
    log.info("第"+i+"条信息,发送结果=Sequence " + sh.sequence
    + "- length " + sh.length + "- command "
    + sh.command + "- status " + sh.status);
    }
    int x=getmess.update(mess);
    count+=x;
    }
    if(count>0)
    log.info("数据更新="+count+"条");
    smppSubmit.closed();
             }
    }
      

  2.   

    楼主要明白,什么是MT,什么是Report。
    你在下发短信的时候,细节上应该是向IO写一个Request和从IO读一个Response。
    但是,如果,你想知道下发短信后,短信是否被手机接收。
    那应该是,等短信被手机接收后,对端网关会向你发送一个状态报告信息(Report)。
    这个状态报告信息,和,下发短信,使用的不是同一个Socket。
      

  3.   

    \
    哦  不是同一个SOCKET?
    谢谢了 我去问问
      

  4.   

    楼主有时间,再仔细研究一下CMPP协议的具体交互过程。据我理解,应该是互为 服务端客户端 的框架结构。当程序要发送信息的时候,充当客户端。
    当程序要接收信息的时候,充当服务端。所以,要想完成和移动网关的对接,你的程序应该会有 服务端功能的代码和客户端功能的代码。我们向手机用户发送短信的方向,一般称为MT。手机用户向我们发送短信的方向,一般称为MO。发送方发送一个消息,具体过程会分成两步,发送Request和接收Response。(例如:下发给手机一条短信)
    接收方接收一个消息,具体过程也会分两步,接收Request和响应Response。(例如:接收手机的一条短信)一般情况下,收发消息的程序中,用户上行的MO消息 和 描述下行MT短信状态的Report消息,是不做严格意义上的区分的。
    只是在处理业务逻辑的过程中,会针对不同的上行信息进行区分处理。 所以,楼主的发送程序,在发送Request之后,不用强制线程等待,可以直接接收对应的Response,
    这个Response只是告诉你,对方已经接收了你的下发内容,但,是否被手机收到,就不知道了。
    当下行短消息被处理完成后(例如:手机收到短信),移动网关会向你发送一个Report信息,来报告刚才下发的短消息被成功处理。
      

  5.   

    这些其实都是 网关厂商规定的。
    中兴做的网关上面,CMPP\SGIP协议都是建立两条链路,即收发链路
    而SMGP和SMPP都是一条链路。
    具体的我也不是很清楚,还是再去问问。
    谢谢诸位兄弟提醒了
      

  6.   

    所以,楼主的发送程序,在发送Request之后,不用强制线程等待,可以直接接收对应的Response, 
    这个Response只是告诉你,对方已经接收了你的下发内容,但,是否被手机收到,就不知道了。 
    当下行短消息被处理完成后(例如:手机收到短信),移动网关会向你发送一个Report信息,来报告刚才下发的短消息被成功处理。 
    很谢谢。
    但我们发移动还要走中间网关。
      

  7.   


    朋友,首先SMGP MO MT都公用同一个通道,但是SMPP  可以是bind_transmitter(发送) bind_receiver(接收) bind_transceiver(收发) 可以是同一个连接完成收发,也可以两个连接 SMPP是SMGP的增强版 SMGP是把MT是把消息发给网关 手机是否收到消息SMPP完全可以知道 通过SMPP协议可以实现短信回执。你可以去看看SMPP3.4 和SMGP3.0对比下。
      

  8.   

    各位都是误导楼主。SMPP协议是短信扩展实体和短信中心之间的协议,不是cmpp。SMPP协议规范上说的很明白,ESMC和SMCC之间互为客户端和服务端。也就是说,你向短信中心提交发送请求的socket要写成客户端,短信中心给你答复del消息的时候,短信中心是客户端,两个是完全不相干的socket。
      

  9.   

    楼主问的问题是说同一个socket的输入流因为输出流阻塞导致连接重置。
    总结一下,一般连接重置会有如下原因导致:  
    1.你的socket队列中没有空间了  
    2.接受者不承认在数据流接口上发送的数据
    3. 抛出的异常也有可能是客户端中断连接。 当客户端中断连接的时候服务器也会抛出这个异常出来。
    就是说客户端正在连接的时候 突然终止 了连接,这样,服务器端会抛出Connection reset by peer 异常出来
    4是在连接断开后的读和写操作引起。
    建议楼主查查自己的代码是否提前断开了socket?