此篇在于分析指令、数据包的流向,分析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)发送给远端。
联系客服