• 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++的方法

     
  • 相关阅读:
    POSTGRESQL 批量权限 管理方法
    centos7安装rabbitmq
    centos7使用cron任务的相关命令(与centos6有区别)
    crontab定时执行shell脚本
    使用kong-dashboard
    Kong组件构成及使用
    Docker基本操作命令
    微服务写的最全的一篇文章
    centos7安装kong和kong-dashboard
    sql练习03
  • 原文地址:https://www.cnblogs.com/luckygxf/p/9211524.html
Copyright © 2020-2023  润新知