DLNA设备的发现

这个过程是从发出search请求开始,到收到匹配设备返回的响应消息,最后,应用程序根据响应消息显示出RemoteDevice信息。

1,发送请求

首先,注册监听DefaultRegistryListener.java,可以统一来用添加、删除、更新本地或远端设备。

upnpService.getRegistry().addListener(deviceListRegistryListener);

它的实现类可以被多个线程并发调用,所以他应该是线程安全的。其中监听的方法都是在一个单独的线程被调用的。

如remoteDeviceAdded(),在一个新发现的设备的完整元数据可用时被调用。

然后,从应用中的upnpService.getControlPoint().search();开始。通过ControlPointImpl.java发起搜索。

不带参数的search()发起搜索类型是:STAllHeader() > "ssdp:all"。

通过DefaultUpnpServiceConfiguration.java中的,ClingExecutor实例将搜索任务被放入一个线程池。

具体搜索任务的类型,通过ProtocolFactoryImpl.java 中的createSendingSearch()来创建。

接着看SendingSearch.java,搜索数据包的信息,搜索请求消息没间隔500毫秒,发送一次,共发送5次。

execute()@SendingSearch.java

OutgoingSearchRequest.java

     super(

                new UpnpRequest(UpnpRequest.Method.MSEARCH),

                ModelUtil.getInetAddressByName(Constants.IPV4_UPNP_MULTICAST_GROUP),

                Constants.UPNP_MULTICAST_PORT

        );

搜索请求,类型:"M-SEARCH"

目标地址:IPV4_UPNP_MULTICAST_GROUP = "239.255.255.250";

目标端口:UPNP_MULTICAST_PORT = 1900;

getUpnpService().getRouter().send(msg); 转到RouterImpl.java通过数据包IO接口实例发出消息。

 Send()@DatagramIOImpl.java

通过DatagramProcessorImpl.java的write完成发送数据包的填充。

最后通过MulticastSocket的send完成发送。

2,接受响应

MulticastSocket是绑定了本机IP地址的套接字,能发送单播、多播数据包,也能接受单播数据包。

在RouterImpl.java中的startAddressBasedTransports()方法,对DatagramIOImpl初始化后,会将其放入线程池运行,所以直接看DatagramIOImpl的run方法。

run() @DatagramIOImpl.java

这里的socket是MulticastSocket对象,负责监听所有发送到本机IP的UDP数据包。

                byte[] buf = new byte[getConfiguration().getMaxDatagramBytes()];

                DatagramPacket datagram = new DatagramPacket(buf, buf.length);

                socket.receive(datagram);

这里的router是RouterImpl.java对象,处理前还是由DatagramProcessorImpl.java中的read方法解读DatagramPacket,转成IncomingDatagramMessage类型对象。

router.received(datagramProcessor.read(localAddress.getAddress(), datagram));

然后看RouterImpl.java如何把接收的响应信息,回到到监听处。

根据消息类型,ProtocolFactoryImpl.java中createReceivingAsync方法负责构建搜索响应的实例。

具体是createReceivingSearchResponse(incomingResponse)方法,最终创建的ReceivingSearchResponse实例,这个实例来处理搜索响应消息的接收。

同样的,ReceivingSearchResponse实例,也会被添加到线程池执行,具体看其execute方法。

execute()@ReceivingSearchResponse.java

这里获取返回搜索响应的远端设备的描述信息,

RemoteDeviceIdentity rdIdentity = new RemoteDeviceIdentity(getInputMessage());

根据远端设备的描述信息,构建RemoteDevice对象。

rd = new RemoteDevice(rdIdentity);

因为这个时候并不知道,这个远端设备是根设备,还是嵌入设备,所以还要去解析它的描述符,然后在处理添加。具体是:

new RetrieveRemoteDescriptors(getUpnpService(), rd)

这个runnable也会在线程池被执行。

run()@RetrieveRemoteDescriptors.java

其中describe()的调用非常耗时,需要确保每次的调用都是必须的,且尽量少的调用。

出去描述符文件等的解析外,跟设备添加有关的调用是:

getUpnpService().getRegistry().addDevice(hydratedDevice);

addDevice(RemoteDevice remoteDevice) @ RegistryImpl.java

add(final RemoteDevice device) @ RemoteItems.java

如下循环完成远端设备的添加:

        for (final RegistryListener listener : registry.getListeners()) {
            registry.getConfiguration().getRegistryListenerExecutor().execute(

                    new Runnable() {
                        public void run() {
                            listener.remoteDeviceAdded(registry, device);

                        }

                    }

            );

        }

通过RegistryListener的具体实现类,把远端设备添加到应用列表中。如DefaultRegistryListener.java,通常应用程序都会集成这个类,并实现其中的接口:

remoteDeviceAdded(),remoteDeviceUpdated()等。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佳哥的技术分享

创作不易,谢谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值