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

📄 receiverbase.java

📁 Short Message Peer to Peer
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 1996-2001
 * Logica Mobile Networks Limited
 * All rights reserved.
 *
 * This software is distributed under Logica Open Source License Version 1.0
 * ("Licence Agreement"). You shall use it and distribute only in accordance
 * with the terms of the License Agreement.
 *
 */
package org.smpp;

import java.io.IOException;

import org.smpp.pdu.PDU;
import org.smpp.pdu.HeaderIncompleteException;
import org.smpp.pdu.MessageIncompleteException;
import org.smpp.pdu.PDUException;
import org.smpp.pdu.UnknownCommandIdException;
import org.smpp.util.ByteBuffer;
import org.smpp.util.ProcessingThread;
import org.smpp.util.Unprocessed;
import org.smpp.util.NotEnoughDataInByteBufferException;

/**
 * Abstract base class for classes which can receive PDUs from connection.
 * The receiving of PDUs can be be performed on background within a separate
 * thread using the <code>ProcessingThread</code> class.
 * 
 * @author Logica Mobile Networks SMPP Open Source Team
 * @version $Revision: 1.4 $
 * @see Receiver
 * @see OutbindReceiver
 * @see Connection
 * @see Transmitter
 * @see Session
 */
public abstract class ReceiverBase extends ProcessingThread {

	/**
	 * Timeout for receiving the rest of PDU from the connection.
	 * If the rest of PDU isn't receive in time, <code>TimeoutException</code>
	 * is thrown.
	 *
	 * @see TimeoutException
	 */
	private long receiveTimeout = Data.RECEIVER_TIMEOUT;


	private byte messageIncompleteRetryCount = 0;


	/**
	 * Method repeatedly called from <code>process</code> method.
	 * It's expected that derived classes implement atomic receive of
	 * one PDU in this method using ReceiverBase's
	 * <code>tryReceivePDUWithTimeout</code> and 
	 * <code>receivePDUFromConnection</code> methods.
	 *
	 * @see #tryReceivePDUWithTimeout(Connection,PDU,long)
	 * @see ProcessingThread#process()
	 * @see ProcessingThread#run()
	 */
	protected abstract void receiveAsync();

	/**
	 * This method should try to receive one PDU from the connection.
	 * It is called in cycle from <code>tryReceivePDUWithTimeout</code> until
	 * timeout expires. The method should check if the actualy received
	 * PDU is equal to the <code>expectedPDU</code>.
	 *
	 * @param connection  the connection from which the PDU should be received
	 * @param expectedPDU the command id and sequence id of the received PDU
	 *                    should be equal to those of expectedPDU
	 * @return the received PDU if any or null if none received
	 *
	 * @exception IOException exception during communication
	 * @exception PDUException incorrect format of PDU
	 * @exception TimeoutException rest of data not received for too long time
	 * @exception UnknownCommandIdException PDU with unknown id was received
	 * @see #tryReceivePDUWithTimeout(Connection,PDU,long)
	 * @see #receiveAsync()
	 * @see #run()
	 * @see PDU#equals(Object)
	 */
	protected abstract PDU tryReceivePDU(Connection connection, PDU expectedPDU)
		throws UnknownCommandIdException, TimeoutException, PDUException, IOException;

	/**
	 * This is an implementation of <code>ProcessingThread</code>'s 
	 * <code>process</code> method, which is method called in loop from
	 * the <code>run</code> method.<br>
	 * This simply calls <code>receiveAsync</code>.
	 */
	public void process() {
		receiveAsync();
	}

	/**
	 * Calls <code>tryReceivePDUWithTimeout(Connection,PDU,long)</code> with
	 * timeout set by <code>setReceiveTimeout</code>.
	 *
	 * @param connection  the connection from which the PDU should be received
	 * @param expectedPDU the command id and sequence id of the received PDU
	 *                    should be equal to those of expectedPDU
	 * @return the received PDU if any or null if none received
	 *
	 * @exception IOException exception during communication
	 * @exception PDUException incorrect format of PDU
	 * @exception TimeoutException rest of data not received for too long time
	 * @exception UnknownCommandIdException PDU with unknown id was received
	 * @see #tryReceivePDUWithTimeout(Connection,PDU,long)
	 */
	final protected PDU tryReceivePDUWithTimeout(Connection connection, PDU expectedPDU)
		throws UnknownCommandIdException, TimeoutException, PDUException, IOException {
		return tryReceivePDUWithTimeout(connection, expectedPDU, getReceiveTimeout());
	}

	/**
	 * For specified time tries to receive a PDU from given connection by 
	 * calling method <code>tryReceivePDU</code>.
	 * The method <code>tryReceivePDU</code> must be implemented in the derived
	 * class.
	 * <p>
	 * The timeout can be either value > 0, then it means for
	 * how many milliseconds will be repeatedly tried to receive a PDU.
	 * If the timeout is = 0 then there is only one attempt to receive a PDU.
	 * If the timeout is equal to Data.RECEIVE_BLOCKING, then the this method
	 * tries receive a PDU until it is received.
	 *
	 * @param connection  the connection from which the PDU should be received
	 * @param expectedPDU the command id and sequence id of the received PDU
	 *                    should be equal to those of expectedPDU
	 * @param timeout     the timeout indication
	 * @return the received PDU if any or null if none received
	 * 
	 * @exception IOException exception during communication
	 * @exception PDUException incorrect format of PDU
	 * @exception TimeoutException rest of data not received for too long time
	 * @exception UnknownCommandIdException PDU with unknown id was received
	 * @see #tryReceivePDU(Connection,PDU)
	 * @see PDU#equals(Object)
	 */
	final protected PDU tryReceivePDUWithTimeout(Connection connection, PDU expectedPDU, long timeout)
		throws UnknownCommandIdException, TimeoutException, PDUException, IOException {
		debug.write(DRXTX, "receivePDU: Going to receive response.");
		long startTime = Data.getCurrentTime();
		PDU pdu = null;
		if (timeout == 0) {
			// with no timeout try just once
			pdu = tryReceivePDU(connection, expectedPDU);
		} else {
			// with timeout keep trying until get some or timeout expires
			while ((pdu == null) && canContinueReceiving(startTime, timeout)) {
				pdu = tryReceivePDU(connection, expectedPDU);
			}
		}
		if (pdu != null) {
			debug.write(DRXTX, "Got pdu " + pdu.debugString());
		}
		return pdu;
	}

	/**
	 * Elementary method receiving data from connection, trying to create
	 * PDU from them and buffering data in case the PDU
	 * isn't still complete. It has timeout checking for incomplete
	 * messages: if the message isn't received completly for certain time
	 * and no new data are received for this time, then exception is thrown
	 * as this could indicate communication problem.
	 *
	 * @param connection the connection to receive the data from
	 * @return either PDU, if complete received or null
	 *
	 * @exception IOException exception during communication
	 * @exception PDUException incorrect format of PDU
	 * @throws TimeoutException rest of data not received for too long time
	 * @throws UnknownCommandIdException PDU with unknown id was received
	 * @see Connection
	 * @see Unprocessed
	 */
	final protected PDU receivePDUFromConnection(Connection connection, Unprocessed unprocessed)
		throws UnknownCommandIdException, TimeoutException, PDUException, IOException {
		debug.write(DRXTXD2, "ReceiverBase.receivePDUFromConnection start");
		PDU pdu = null;
		ByteBuffer buffer;
		ByteBuffer unprocBuffer;
		
		try {
			// first check if there is something left from the last time
			if (unprocessed.getHasUnprocessed()) {
				unprocBuffer = unprocessed.getUnprocessed();
				debug.write(DRXTX, "have unprocessed " + unprocBuffer.length() + " bytes from previous try");
				pdu = tryGetUnprocessedPDU(unprocessed);
			}
			if (pdu == null) { // only if we didn't manage to get pdu from unproc
				buffer = connection.receive();
				unprocBuffer = unprocessed.getUnprocessed();
				// if received something now or have something from the last receive
				if (buffer.length() != 0) {
					unprocBuffer.appendBuffer(buffer);

⌨️ 快捷键说明

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