android 网络框架 源码分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 函数, 至此,我们分析完毕






























以上是关于android 网络框架 源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

Android网络框架源码分析一---Volley

android-async-http框架源码分析

OkHttpOkHttp 源码分析 ( 网络框架封装 | OkHttp 4 迁移 | OkHttp 建造者模式 )

android-----Volley框架源码分析