public class SipProvider implements Configurable, TransportListener
實現TransportListener的目的是什麼?簡單,爲了實現回調,SipProvider實現了TransportListener,記住-這個很重要.
數據發送對應的流程對應如下,再這裏假設message就是已經生成好了的(實際上的message涉及到很多的協議,搞了很長時候,這會還在犯暈)
SipdroidProvider----UdpTransport-UdpProvider-UdpSocket
UdpSocket擁有我們最直接的兩個方法:send receive,方法原型如下:
- /** Receives a datagram packet from this socket. */
- public void receive(UdpPacket pkt) throws java.io.IOException {
- DatagramPacket dgram = pkt.getDatagramPacket();
- socket.receive(dgram);
- pkt.setDatagramPacket(dgram);
- }
- /** Sends an UDP packet from this socket. */
- public void send(UdpPacket pkt) throws java.io.IOException {
- socket.send(pkt.getDatagramPacket());
-
}
複製代碼
UdpProvider擁有UdpSocket,依託UdpSocket來實現數據的收發,但是receive是阻塞的,這個大家詳細緣由看我的另一篇文章:
http://www.shouyanwang.org/thread-5-1-1.html
因此UdpProvider必然要繼承thread來讓自己成爲線程:
- /** The main thread */
- public void run() {
- byte[] buf = new byte[BUFFER_SIZE];
- UdpPacket packet = new UdpPacket(buf, buf.length);//UdpPacket是DataProgramPacket更深層次的一封裝
- Exception error = null;
- long expire = 0;
- if (alive_time > 0)
- expire = System.currentTimeMillis() + alive_time;
- try {
- // socket.setSoTimeout(socket_timeout); modified
- // loop
- while (!stop) {
- try {
- socket.receive(packet);
- } catch (InterruptedIOException ie) {
- if (alive_time > 0 && System.currentTimeMillis() > expire)
- halt();
- continue;
- }
- if (packet.getLength() >= minimum_length) {
- if (listener != null)
- listener.onReceivedPacket(this, packet);///嚴重注意這裏
- if (alive_time > 0)
- expire = System.currentTimeMillis() + alive_time;
- }
- packet = new UdpPacket(buf, buf.length);
- }
- } catch (Exception e) {
- error = e;
- stop = true;
- }
- is_running = false;
- if (listener != null)
- listener.onServiceTerminated(this, error);
- listener = null;
-
}
複製代碼
UdpProvider中有一個UdpProviderListener,在UdpProvider進行初始化的時候便指定了
Siproid----UdpTransport-UdpProvider-UdpSocket(仔細看這個初始化的流程圖,我給出它們的構造函數)
public UdpProvider(UdpSocket socket, UdpProviderListener listener) //UdpProvider構造函數
public UdpTransport(int port, TransportListener listener)//UdpTransProt構造函數,UdpTransport實現了UdpProviderListener
udp = new UdpTransport(host_port, host_ipaddr, Sipdroid.this);
所以流程是怎麼樣的呢?
客戶端接收到服務器返回的數據後,首先是在UdpProvider的run裏面的,上面的紅色字體注意沒,UdpProvider會用UdpProviderListener進行回調,UdpProviderListener是誰呢,是UdpTransport,因爲UdpTransport實現了UdpProviderListener接口,並在自己的構造函數中將自己作爲參數傳遞給了UdpProvider.
好了,數據已經到了UdpTransport手裏了,看下面的UdpTransport是如何實現的?
/** When a new UDP datagram is received. */
public void onReceivedPacket(UdpProvider udp, UdpPacket packet) {
Message msg = new Message(packet);
msg.setRemoteAddress(packet.getIpAddress().toString());
msg.setRemotePort(packet.getPort());
msg.setTransport(PROTO_UDP);
if (listener != null)
listener.onReceivedMessage(this, msg);
}
UdpTransport同樣只需要調用onReceivedMessage就可以將數據傳回給SipProvider呢,這樣SipProvider便獲得了從服務器返回的信息,然後程序在獲得信息後要做的就是對Message解析,並進行適配,確定手機客戶端這邊怎麼來響應。
通俗點說是上級將接口傳遞給下級,下級在獲得數據後便通過該接口將數據返回給上級.