打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ADB源码分析(二)

此篇在于分析指令、数据包的流向,分析local socket与smart socket、remote socket的关联以及分析PC与Android设备是如何传递数据信息的(从本地转发到远端)

一、client,server---HOST端(PC)详细分析

以adb installe分析:

1、main() -->adb_commandline() --> install_app()

2、do_sync_push() //pc传输文件到手机本地

adb_connect("sync:")--> _adb_connect("host:version") --> socket_loopback_client()

连接adb server,server端触发ss_listener_event_func(),client端使用adb_connect后获得的fd, write(adb_connect后的fd)和read(adb_connect后的fd)直接和server进行通信。

在ss_listener_event_func()中:

1)nfd =adb_socket_accept(_fd, &addr, &alen) ,server端读写nfd对不同的client进行读写操作。

2)创建local_socket并监听它的读写事件: s = create_local_socket(fd).

fdevent_install(&s->fde,fd, local_socket_event_func, s);

client端有数据发送就触发local_socket_event_func函数,用作本地socket的数据处理。

3)创建一个smart_socket并作为s的peer:connect_to_smartsocket(s).

注:当adb client发送消息时,触发adb server的监视事件 --> 触发local_socket_event_func()的FDE_READ事件,调用 r = s->peer->enqueue(s->peer, p)(此时的s-->peer 即smart_socket,s->peer->enqueue为smart_socket_enqueue。当PC发送open指令,device应答okey,PC端和device端衔接成功后,s-->peer 变为remote_socket,s->peer->enqueue变为remote_socket_enqueue)。在smart_socket_enqueue()中会判断client端输入的服务是否在本地可以处理,如果在本地可以直接处理的,调用handle_host_request,如果本地处理不了,调用connect_to_remote(s->peer, (char *)(p->data + 4)) 发送A_OPEN


二、device端(Android设备)详细分析

手机端接收到A_OPEN后:

在adb.c的handle_packet中case A_OPEN:

①执行s = create_local_service_socket(name);

1)fd =service_to_fd(name);

-->ret =create_service_thread();// create_service_thread中创建一对socketpair,其中一个pair--s[1](即fd:本地socket的一端)作为新开启线程的一个参数(fd),而另一个pair--s[0]作为ret返回。根据步骤2),s[0]作为参数创建本地socket,并监听读取事件。

注:在create_service_thread()开启的线程中,直接读/写参数中的fd,这样就把数据读/写到了本地socket的一端s[1],就可以触发本地socket的另一端s[0]读/写事件,调用本地socket的local_socket_event_func函数对数据进行处理。

2)s =create_local_socket(fd); //根据fd创建local_asocket,并监听读取

②执行s->peer= create_remote_socket(p->msg.arg0, t); //把device端local_socket和remote_socket(注:remote端的s->id为PC端local s->id)互为peer

调用send_ready(s->id, s->peer->id, t); //transport层发送OKAY给PC端

PC第一次接收到A_OKAY后:

执行 s= find_local_socket(p->msg.arg1) //根据s->id获取本地的local_socket

如果s->peer=0,则调用 create_remote_socket(p->msg.arg0, t); //创建remote_socket,s->peer->enqueue= remote_socket_enqueue

执行s->ready(s); // local_socket_ready_notify

详细通信框架图:



进一步分析:

pc向device发送A_OPEN前:


当client有数据,发送给server,server触发ss_listener_event_func,响应连接后返回fd,用此fd创建localsocket后,又创建了smart socket,和localsocket互为peer。调用smart socket的smart_socket_enqueue处理client命令。

pc向device发送A_OPEN后:


调用smartsocket的smart_socket_enqueue处理client命令后,如果本地处理不了的命令,将connect_to_remote交给远端去处理并将自己(smart socket)从local socket摘除,connect_to_remote函数将发送A_OPEN给device端。device端接收到A_OPEN,将创建local socket和remote socket,并将local和remote置为peer(remotesocket的ID为PC端local socket的ID)后,发送A_OKEY给PC端,PC端收到后数据包后,先通过查询本地socket后,创建出remote socket。并将PC localsocket和remote socket置为peer(PC中的remotesocket的ID为device端local socket的ID)。


三、传输层(transport.c)详细分析

transport.c中:

①transport注册

init_transport_registration();

-->adb_socketpair(s)//创建socketpair

   transport_registration_send = s[0];

   transport_registration_recv = s[1];

fdevent_install(&transport_registration_fde,transport_registration_recv,transport_registration_func,0);

fdevent_set(&transport_registration_fde,FDE_READ);

注:当transport_registration_send有写事件的时候触发transport_registration_recv的读事件,回调transport_registration_func函数。什么时候能触发transport_registration_send的写事件?即当有transport需要被注册的时候,就会调用register_transport,进而调用transport_write_action(transport_registration_send, &m),这样就会触发transport_registration_recv。

在transport_registration_func函数中:

-->adb_socketpair(s))//创建socketpair

    t->transport_socket = s[0];

    t->fd = s[1];

fdevent_install(&(t->transport_fde),t->transport_socket, transport_socket_events, t); //当有数据写入t->fd,会触发t->transport_socket读事件,调用transport_socket_events用于进一步处理远端发送过来的数据包。

fdevent_set(&(t->transport_fde),FDE_READ); //监听读事件

开了两个线程:

adb_thread_create(&input_thread_ptr,input_thread, t))

adb_thread_create(&output_thread_ptr,output_thread, t))

②从远端读取数据写入本地socket

output_thread==>t->read_from_remote(p, t);

等待远端数据,将远端发送过来的数据写入t->fd句柄,这样与t->fd相pair的t->transport_socket句柄就接收到该数据了,然后触发transport_socket_events后调用==>handle_packet处理远端数据发送过来的数据包。
host端:函数find_local_socket(p->msg.arg1)用来查寻本地s->id值为p->msg.arg1的local_socket,直接调用本地local_socket的s->enqueue(s, p);即local_socket_enqueue, local_socket_enqueue函数又将调用adb_write(s->fd, p->ptr, p->len);将数据发送给s->fd,该s->fd是由ss_listener_event_func函数创建的一个fd = adb_socket_accept(_fd, &addr, &alen);所以向s->fd发送数据就表示将数据发送给了与host端口#define ADB_PORT 5037建立网络连接的client,这些命令正在pending读取与host端口5037建立连接的句柄fd发送数据过来.

device端:函数find_local_socket(p->msg.arg1)用来查寻本地s->id值为p->msg.arg1的local_socket,直接调用本地local_socket的s->enqueue(s, p);即local_socket_enqueue,local_socket_enqueue函数又将调用adb_write(s->fd, p->ptr, p->len);将数据发送给s->fd,该s->fd是由create_local_service_socket函数创建的一个fd = service_to_fd(name);所以向s->fd发送数据就表示将数据发送给了与该fd(s[0])相pair的s[1](tfd), s[1](tfd)正在pending读取fd(s[0])发送数据过来.

③从本地socket读取数据包写入远端

②input_thread等待t->fd句柄有数据到来,数据由与t->fd相pair的t->transport_socket句柄写入

通过send_packet函数==>
write_packet(t->transport_socket, &p)发送过来,之后input_thread将接收到得数据通过t->write_to_remote(p, t)发送给远端。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
再次浅析adb shell,pc daemon和手机daemon三者之间的数据交互流程
服务器如何在SOCKET通讯中知道客户端断开连接或掉线了???[
Socket error: Connection reset by peer.
TCP短连接产生大量TIME
tomcat设置远程连接
JPDA 利用Eclipse和Tomcat进行远程调试
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服