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解析,并进行适配,确定手机客户端这边怎么来响应。
通俗点说是上级将接口传递给下级,下级在获得数据后便通过该接口将数据返回给上级.
补充下,其实看了上面的分析后大家也能够从侧面推荐下作者的设计意图,必然有类继承UdpTransport来实现更高界别的Transport,在拥有更高界别UdpTransport会话的同时,必然会有对应的更高级别的UdpProvider