android 网络框架 源码分析

少年恃险若平地,独倚长剑凌清秋。这篇文章主要讲述android 网络框架 源码分析相关的知识,希望能为你提供帮助。
android 网络框架 源码分析


导语:

最近想开发一个协议分析工具,来监控android app 所有的网络操作行为, 由于android 开发分为java层,和Native层, 对于Native层我们只要对linux下所有网络I/O接口进行拦截即可,对于java 层,笔者对android 网络框架不是很了解,所以这个工具开发之前,笔者需要对android 的网络框架进行一个简单的分析。






分析结论:



1. android 的网络框架都是基于Socket类实现的
2. java 层Socket具体实现和平台喜相关,最终I/O操作实现调用C库函数完成
3. 我们可以在Native层 拦截Linux下接网络I/O 接口来完成对android app 所有网络操作行为的捕获






分析情景1: 
android很多框架都是基于Socket类基础进行的,所以我们从Socket类开始分析, 一下是一个我们常用使用Socket的案例

< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> Sokect client = new Socket("127.0.0.1", 5555); PrintWriter out = new PrintWriter(client.getOutputStream()); out.println("hello world"); < /span>

我们发现关键函数实现是是getOutputStream,   如何获取一个输出流。


  Socket. getOutputStream: 
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> public OutputStream getOutputStream() throws IOException { checkOpenAndCreate(false); if (isOutputShutdown()) { throw new SocketException("Socket output is shutdown"); } return impl.getOutputStream(); }< /span>

从这个方法的实现,主要在于 我们  final SocketImpl impl, 我们看看这个的对象初始化, 参见够默认构造函数
Socket.Socket:  \libcore\luni\src\main\java\java\net\Socket.java
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> /** * Creates a new unconnected socket. When a SocketImplFactory is defined it * creates the internal socket implementation, otherwise the default socket * implementation will be used for this socket. * * @see SocketImplFactory * @see SocketImpl */ public Socket() { this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(); this.proxy = null; }< /span>

我们看看PlainSocketImpl.getOutstream

< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> @Override protected synchronized OutputStream getOutputStream() throws IOException { checkNotClosed(); return new SocketOutputStream(this); }< /span>

所以我们调用Soccket.getOutstream   返回的是一个SocketOutputStream。然后通过这个对象进行I/O 操作, 我们分析其中一个I/O操作------write.


SocketOutputStream.write:  \libcore\luni\src\main\java\org\apache\harmony\luni\net\SocketOutputStream.java

< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> @Override public void write(byte[] buffer, int offset, int count) throws IOException { if (buffer == null) { throw new NullPointerException("buffer == null"); } if (0 < = offset & & offset < = buffer.length & & 0 < = count & & count < = buffer.length - offset) { socket.write(buffer, offset, count); } else { throw new ArrayIndexOutOfBoundsException(); } }< /span>

发现具体实现在Line 7,socket.write(buffer, offset, count) , 这个  socket的声明: private PlainSocketImpl socket; 初始化在构造函数中
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> public SocketOutputStream(SocketImpl socket) { super(); this.socket = (PlainSocketImpl) socket; }< /span>



继续分析PlainSocketImpl.write
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> int write(byte[] buffer, int offset, int count) throws IOException { if (streaming) { return netImpl.write(fd, buffer, offset, count); } else { return netImpl.send(fd, buffer, offset, count, port, address); } }< /span>

stream 默认为true即(TCP), netImpl 是一个和平台相关的对象, 如下
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> protected INetworkSystem netImpl = Platform.getNetworkSystem(); private boolean streaming = true; < /span>

我们看看 Platform.getNetworkSystem()
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> public static INetworkSystem getNetworkSystem() { accessCheck(); // TODO: use BlockGuard here too, like in getFileSystem() above. return NETWORK_SYSTEM; }< /span>

NETWORK_SYSTEM 参见

< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> private static final INetworkSystem NETWORK_SYSTEM = new BlockGuard.WrappedNetworkSystem(OSNetworkSystem.getOSNetworkSystem()); < /span>

BlockGuard.WrappedNetworkSystem 只是对对象进行简单的封装,具体实现在OSNetworkSystem.getOSNetworkSystem()

分析:OSNetworkSystem.getOSNetworkSystem
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> /** * This wraps native code that implements the INetworkSystem interface. * Address length was changed from long to int for performance reasons. */ final class OSNetworkSystem implements INetworkSystem { private static final OSNetworkSystem singleton = new OSNetworkSystem(); public static OSNetworkSystem getOSNetworkSystem() { return singleton; }private OSNetworkSystem() { } public native void accept(FileDescriptor serverFd, SocketImpl newSocket, FileDescriptor clientFd) throws IOException; public native void bind(FileDescriptor fd, InetAddress inetAddress, int port) throws SocketException; public native void connect(FileDescriptor fd, InetAddress inetAddress, int port, int timeout) throws SocketException; public native boolean connectNonBlocking(FileDescriptor fd, InetAddress inetAddress, int port) throws IOException; public native boolean isConnected(FileDescriptor fd, int timeout) throws IOException; public native void socket(FileDescriptor fd, boolean stream) throws SocketException; public native void disconnectDatagram(FileDescriptor fd) throws SocketException; public native InetAddress getSocketLocalAddress(FileDescriptor fd); public native int getSocketLocalPort(FileDescriptor fd); public native Object getSocketOption(FileDescriptor fd, int opt) throws SocketException; public native void listen(FileDescriptor fd, int backlog) throws SocketException; public native int read(FileDescriptor fd, byte[] data, int offset, int count) throws IOException; public native int readDirect(FileDescriptor fd, int address, int count) throws IOException; public native int recv(FileDescriptor fd, DatagramPacket packet, byte[] data, int offset, int length, boolean peek, boolean connected) throws IOException; public native int recvDirect(FileDescriptor fd, DatagramPacket packet, int address, int offset, int length, boolean peek, boolean connected) throws IOException; static native boolean selectImpl(FileDescriptor[] readfd,FileDescriptor[] writefd, int cread, int cwirte, int[] flags, long timeout); public native int send(FileDescriptor fd, byte[] data, int offset, int length, int port, InetAddress inetAddress) throws IOException; public native int sendDirect(FileDescriptor fd, int address, int offset, int length, int port, InetAddress inetAddress) throws IOException; public native void sendUrgentData(FileDescriptor fd, byte value); public native void setInetAddress(InetAddress sender, byte[] address); public native void setSocketOption(FileDescriptor fd, int opt, Object optVal) throws SocketException; public native void shutdownInput(FileDescriptor fd) throws IOException; public native void shutdownOutput(FileDescriptor fd) throws IOException; public native void close(FileDescriptor fd) throws IOException; public native int write(FileDescriptor fd, byte[] data, int offset, int count) throws IOException; public native int writeDirect(FileDescriptor fd, int address, int offset, int count) throws IOException; }< /span>

【android 网络框架 源码分析】这里提供所有关网络操作的接口,这些函数在本地代码实现,是文件中实现:libcore\luni\src\main\native\org_apache_harmony_luni_platform_OSNetworkSystem.cpp, 我们分析其中一个I/O操作---- write:OSNetworkSystem_write
OSNetworkSystem_write:libcore\luni\src\main\native\org_apache_harmony_luni_platform_OSNetworkSystem.cpp
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> static jint OSNetworkSystem_write(JNIEnv* env, jobject, jobject fileDescriptor, jbyteArray byteArray, jint offset, jint count) { ScopedByteArrayRW bytes(env, byteArray); if (bytes.get() == NULL) { return -1; } jint address = static_cast< jint> (reinterpret_cast< uintptr_t> (bytes.get())); int result = OSNetworkSystem_writeDirect(env, NULL, fileDescriptor, address, offset, count); return result; }< /span>

Line 8:调用OSNetworkSystem_writeDirect 完成操作
< span data-wiz-span="data-wiz-span" style="font-family: ‘Courier New‘; "> static jint OSNetworkSystem_writeDirect(JNIEnv* env, jobject, jobject fileDescriptor, jint address, jint offset, jint count) { if (count < = 0) { return 0; }NetFd fd(env, fileDescriptor); if (fd.isClosed()) { return 0; }jbyte* src = https://www.songbingjia.com/android/reinterpret_cast< jbyte*> (static_cast< uintptr_t> (address + offset)); ssize_t bytesSent; { int intFd = fd.get(); AsynchronousSocketCloseMonitor monitor(intFd); bytesSent = NET_FAILURE_RETRY(fd, write(intFd, src, count)); } if (env-> ExceptionOccurred()) { return -1; }if (bytesSent == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // We were asked to write to a non-blocking socket, but were told // it would block, so report"no bytes written". return 0; } else { jniThrowSocketException(env, errno); return 0; } } return bytesSent; }< /span>

line 18: 具体调用libc 含糊write 函数, 至此,我们分析完毕



来自为知笔记(Wiz)


























    推荐阅读