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>

这里提供所有关网络操作的接口,这些函数在本地代码实现,是文件中实现: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 = 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)

相关文章