Java Socket, DatagramSocket, ServerSocketChannel io代码跟踪

Java Socket, DatagramSocket, ServerSocketChannel这三个分别对应了,TCP, udp, NIO通信API封装。JDK封装了,想跟下代码,看下具体最后是怎么实现的。

都是通过native方法实现的。

下面是具体代码的跟进

1. Socket

                Socket clientSocket = serverSocket.accept();
InputStream is
= clientSocket.getInputStream();
byte buff[] = new byte[1024];
length
= is.read(buff);

上面的代码片段是从Socket读取数据的代码。跟进clientSocket.getInputStream()

/**
     * Gets an InputStream for this socket.
     */
    protected synchronized InputStream getInputStream() throws IOException {
        synchronized (fdLock) {
            if (isClosedOrPending())
                throw new IOException("Socket Closed");
            if (shut_rd)
                throw new IOException("Socket input is shutdown");
            if (socketInputStream == null)
                socketInputStream = new SocketInputStream(this);
        }
        return socketInputStream;
    }

这里拿到的是SocketInputStream对象,跟进SocketInputStream.read(byte[] buf)

/**
     * Reads into a byte array data from the socket.
     * @param b the buffer into which the data is read
     * @return the actual number of bytes read, -1 is
     *          returned when the end of the stream is reached.
     * @exception IOException If an I/O error has occurred.
     */
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

继续跟进

/**
     * Reads into a byte array <i>b</i> at offset <i>off</i>,
     * <i>length</i> bytes of data.
     * @param b the buffer into which the data is read
     * @param off the start offset of the data
     * @param length the maximum number of bytes read
     * @return the actual number of bytes read, -1 is
     *          returned when the end of the stream is reached.
     * @exception IOException If an I/O error has occurred.
     */
    public int read(byte b[], int off, int length) throws IOException {
        return read(b, off, length, impl.getTimeout());
    }

继续跟进

int read(byte b[], int off, int length, int timeout) throws IOException {
        int n;

        // EOF already encountered
        if (eof) {
            return -1;
        }

        // connection reset
        if (impl.isConnectionReset()) {
            throw new SocketException("Connection reset");
        }

        // bounds check
        if (length <= 0 || off < 0 || length > b.length - off) {
            if (length == 0) {
                return 0;
            }
            throw new ArrayIndexOutOfBoundsException("length == " + length
                    + " off == " + off + " buffer length == " + b.length);
        }

        boolean gotReset = false;

        // acquire file descriptor and do the read
        FileDescriptor fd = impl.acquireFD();
        try {
            n = socketRead(fd, b, off, length, timeout);
            if (n > 0) {
                return n;
            }
        } catch (ConnectionResetException rstExc) {
            gotReset = true;
        } finally {
            impl.releaseFD();
        }

        /*
         * We receive a "connection reset" but there may be bytes still
         * buffered on the socket
         */
        if (gotReset) {
            impl.setConnectionResetPending();
            impl.acquireFD();
            try {
                n = socketRead(fd, b, off, length, timeout);
                if (n > 0) {
                    return n;
                }
            } catch (ConnectionResetException rstExc) {
            } finally {
                impl.releaseFD();
            }
        }

        /*
         * If we get here we are at EOF, the socket has been closed,
         * or the connection has been reset.
         */
        if (impl.isClosedOrPending()) {
            throw new SocketException("Socket closed");
        }
        if (impl.isConnectionResetPending()) {
            impl.setConnectionReset();
        }
        if (impl.isConnectionReset()) {
            throw new SocketException("Connection reset");
        }
        eof = true;
        return -1;
    }
socketRead(fd, b, off, length, timeout);跟进
private int socketRead(FileDescriptor fd,
                           byte b[], int off, int len,
                           int timeout)
        throws IOException {
        return socketRead0(fd, b, off, len, timeout);
    }

继续跟进

private native int socketRead0(FileDescriptor fd,
                                   byte b[], int off, int len,
                                   int timeout)

2. DatagramSocket

clientSocket = new DatagramSocket();
packetToSend = new DatagramPacket(buff, buff.length, InetAddress.getByName("127.0.0.1"), 10002);
clientSocket.send(packetToSend);                                                    //发送数据包

跟进send()

public void send(DatagramPacket p) throws IOException  {
        InetAddress packetAddress = null;
        synchronized (p) {
            if (isClosed())
                throw new SocketException("Socket is closed");
            checkAddress (p.getAddress(), "send");
            if (connectState == ST_NOT_CONNECTED) {
                // check the address is ok wiht the security manager on every send.
                SecurityManager security = System.getSecurityManager();

                // The reason you want to synchronize on datagram packet
                // is because you don't want an applet to change the address
                // while you are trying to send the packet for example
                // after the security check but before the send.
                if (security != null) {
                    if (p.getAddress().isMulticastAddress()) {
                        security.checkMulticast(p.getAddress());
                    } else {
                        security.checkConnect(p.getAddress().getHostAddress(),
                                              p.getPort());
                    }
                }
            } else {
                // we're connected
                packetAddress = p.getAddress();
                if (packetAddress == null) {
                    p.setAddress(connectedAddress);
                    p.setPort(connectedPort);
                } else if ((!packetAddress.equals(connectedAddress)) ||
                           p.getPort() != connectedPort) {
                    throw new IllegalArgumentException("connected address " +
                                                       "and packet address" +
                                                       " differ");
                }
            }
            // Check whether the socket is bound
            if (!isBound())
                bind(new InetSocketAddress(0));
            // call the  method to send
            getImpl().send(p);
        }

继续

    protected native void send(DatagramPacket p) throws IOException;

这里最后调用native方法

3.ServerSocketChannel

            SocketChannel client = server.accept();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            client.read(buffer);

继续

public abstract int read(ByteBuffer dst) throws IOException;

继续

public int read(ByteBuffer var1) throws IOException {
        if (var1 == null) {
            throw new NullPointerException();
        } else {
            Object var2 = this.readLock;
            synchronized(this.readLock) {
                if (!this.ensureReadOpen()) {
                    return -1;
                } else {
                    int var3 = 0;
                    boolean var20 = false;

                    byte var10000;
                    byte var5;
                    label356: {
                        int var27;
                        try {
                            var20 = true;
                            this.begin();
                            Object var4 = this.stateLock;
                            synchronized(this.stateLock) {
                                if (!this.isOpen()) {
                                    var5 = 0;
                                    var20 = false;
                                    break label356;
                                }

                                this.readerThread = NativeThread.current();
                            }

                            while(true) {
                                var3 = IOUtil.read(this.fd, var1, -1L, nd);
                                if (var3 != -3 || !this.isOpen()) {
                                    var27 = IOStatus.normalize(var3);
                                    var20 = false;
                                    break;
                                }
                            }
                        } finally {
                            if (var20) {
                                label271: {
                                    this.readerCleanup();
                                    this.end(var3 > 0 || var3 == -2);
                                    Object var11 = this.stateLock;
                                    synchronized(this.stateLock) {
                                        if (var3 > 0 || this.isInputOpen) {
                                            break label271;
                                        }

                                        var10000 = -1;
                                    }

                                    return var10000;
                                }

                                assert IOStatus.check(var3);

                            }
                        }

                        label303: {
                            this.readerCleanup();
                            this.end(var3 > 0 || var3 == -2);
                            Object var28 = this.stateLock;
                            synchronized(this.stateLock) {
                                if (var3 > 0 || this.isInputOpen) {
                                    break label303;
                                }

                                var10000 = -1;
                            }

                            return var10000;
                        }

                        assert IOStatus.check(var3);

                        return var27;
                    }

                    this.readerCleanup();
                    this.end(var3 > 0 || var3 == -2);
                    Object var6 = this.stateLock;
                    synchronized(this.stateLock) {
                        if (var3 <= 0 && !this.isInputOpen) {
                            var10000 = -1;
                            return var10000;
                        }
                    }

                    assert IOStatus.check(var3);

                    return var5;
                }
            }
        }
    }
继续
static int read(FileDescriptor var0, ByteBuffer var1, long var2, NativeDispatcher var4) throws IOException {
        if (var1.isReadOnly()) {
            throw new IllegalArgumentException("Read-only buffer");
        } else if (var1 instanceof DirectBuffer) {
            return readIntoNativeBuffer(var0, var1, var2, var4);
        } else {
            ByteBuffer var5 = Util.getTemporaryDirectBuffer(var1.remaining());

            int var7;
            try {
                int var6 = readIntoNativeBuffer(var0, var5, var2, var4);
                var5.flip();
                if (var6 > 0) {
                    var1.put(var5);
                }

                var7 = var6;
            } finally {
                Util.offerFirstTemporaryDirectBuffer(var5);
            }

            return var7;
        }
    }

继续

private static int readIntoNativeBuffer(FileDescriptor var0, ByteBuffer var1, long var2, NativeDispatcher var4) throws IOException {
        int var5 = var1.position();
        int var6 = var1.limit();

        assert var5 <= var6;

        int var7 = var5 <= var6 ? var6 - var5 : 0;
        if (var7 == 0) {
            return 0;
        } else {
            boolean var8 = false;
            int var9;
            if (var2 != -1L) {
                var9 = var4.pread(var0, ((DirectBuffer)var1).address() + (long)var5, var7, var2);
            } else {
                var9 = var4.read(var0, ((DirectBuffer)var1).address() + (long)var5, var7);
            }

            if (var9 > 0) {
                var1.position(var5 + var9);
            }

            return var9;
        }
    }

继续

int read(FileDescriptor var1, long var2, int var4) throws IOException {
        return FileDispatcherImpl.read0(var1, var2, var4);
    }

继续

static native int read0(FileDescriptor var0, long var1, int var3) throws IOException;

最后都是native方法

JVM是c++. c实现的,最后调用的应该是c/c++的方法

 
原文地址:https://www.cnblogs.com/luckygxf/p/9211524.html