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++的方法
Java Socket, DatagramSocket, ServerSocketChannel io代码跟踪的更多相关文章
- Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)
		声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ... 
- Java Socket长连接示例代码
		SocketListenerPusher.java代码如下: import java.io.IOException; import java.net.InetSocketAddress; import ... 
- Java Socket通信读取相关信息代码
		转自:http://developer.51cto.com/art/201003/190206.htm Java Socket通信读取有不少需要我们注意的知识点.当我们在使用的时候有很多的问题摆在我们 ... 
- Java Socket/HttpURLConnection读取HTTP网页
		以读取百度的http网页为例.如果知道了IP地址和端口,然后新建一个Socket,就直接去读百度的首页,根本没反应,原因是www.baidu.com是以http协议传输的,而现在要以Socket原始的 ... 
- Java Socket IO(BIO、NIO)
		总结下Java socket IO.首先是各种IO的定义,这个定义似乎也是众说纷纭.我按照stackoverflow上面的解释: IO有两种分法:按照阻塞或者按照同步.按照阻塞,有阻塞IO和非阻塞IO ... 
- java scoket Blocking 阻塞IO socket通信四
		记住NIO在jdk1.7版本之前是同步非阻塞的,以前的inputsream是同步阻塞的,上面学习完成了Buffer现在我们来学习channel channel书双向的,以前阻塞的io的inputstr ... 
- java socket编程实例代码
		1.所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 两性话题 两性 ... 
- java scoket Blocking 阻塞IO socket通信一
		package bhz.bio; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; p ... 
- java 提供了哪些IO方式
		今天听了杨晓峰老师的java 36讲,感觉IO这块是特别欠缺的,所以讲义摘录如下: 欢迎大家去订阅: 本文章转自:https://time.geekbang.org/column/article/83 ... 
随机推荐
- winform datagridview某一列设为自动宽度
			如果用displayedcells只会使看见的数据自动列宽,滚动条往下发现后面的没有自动列宽,所以要用allcells就不会出现这个问题 
- linux下 zip解压 tar解压 gz解压 bz2等各种解压文件命令
			.tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) ——————————————— .gz 解压 ... 
- 使用过多的递归出现错误,“System.StackOverflowException”类型的未经处理的异常在 mscorlib.dll 中发生
			class Program { static void Main(string[] args) { sub(0); } private static void sub(int count) { ... 
- 9.tab栏切换
			<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ... 
- Centos7.4 更换国内yum源
			1.进入yum源配置文件夹.(配置之前先看看有没有安装wget命令呢,没的话可以先用当前的yum源安装一下再说.yum -y install wget) 2.转到配置文件目录 cd /etc/yum ... 
- Query on a tree II  倍增LCA
			You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ... 
- [JLOI2015]管道连接(斯坦纳树)
			[Luogu3264] 原题解 多个频道,每个频道的关键点要求相互联通 详见代码,非常巧妙 #include<cstdio> #include<iostream> #inclu ... 
- CNN 卷积神经网络结构
			cnn每一层会输出多个feature map, 每个Feature Map通过一种卷积滤波器提取输入的一种特征,每个feature map由多个神经元组成,假如某个feature map的shape是 ... 
- AtCoder Beginner Contest 113 A
			A - Discount Fare Time limit : 2sec / Memory limit : 1024MB Score: 100 points Problem Statement Ther ... 
- 在Linux系统下用dd命令制作ISO镜像U盘启动盘
			http://os.51cto.com/art/201510/494762.htm 首先在 Linux 系统中打开终端,确认 U 盘路径: sudo fdisk -l 使用 dd 命令,格式如下: s ... 
