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代码跟踪的更多相关文章

  1. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  2. Java Socket长连接示例代码

    SocketListenerPusher.java代码如下: import java.io.IOException; import java.net.InetSocketAddress; import ...

  3. Java Socket通信读取相关信息代码

    转自:http://developer.51cto.com/art/201003/190206.htm Java Socket通信读取有不少需要我们注意的知识点.当我们在使用的时候有很多的问题摆在我们 ...

  4. Java Socket/HttpURLConnection读取HTTP网页

    以读取百度的http网页为例.如果知道了IP地址和端口,然后新建一个Socket,就直接去读百度的首页,根本没反应,原因是www.baidu.com是以http协议传输的,而现在要以Socket原始的 ...

  5. Java Socket IO(BIO、NIO)

    总结下Java socket IO.首先是各种IO的定义,这个定义似乎也是众说纷纭.我按照stackoverflow上面的解释: IO有两种分法:按照阻塞或者按照同步.按照阻塞,有阻塞IO和非阻塞IO ...

  6. java scoket Blocking 阻塞IO socket通信四

    记住NIO在jdk1.7版本之前是同步非阻塞的,以前的inputsream是同步阻塞的,上面学习完成了Buffer现在我们来学习channel channel书双向的,以前阻塞的io的inputstr ...

  7. java socket编程实例代码

    1.所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 两性话题 两性 ...

  8. java scoket Blocking 阻塞IO socket通信一

    package bhz.bio; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; p ...

  9. java 提供了哪些IO方式

    今天听了杨晓峰老师的java 36讲,感觉IO这块是特别欠缺的,所以讲义摘录如下: 欢迎大家去订阅: 本文章转自:https://time.geekbang.org/column/article/83 ...

随机推荐

  1. php 中 include 与 require 的区别

    以下内容转自:https://blog.csdn.net/hsd2012/article/details/51089785 网上太多关于php中include与require区别.其实说的都是经不起验 ...

  2. time、random以及序列化模块

    一. time模块 在Python中,通常有这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行“type( ...

  3. Qt 学习之路 2(74):线程和 QObject

    Home / Qt 学习之路 2 / Qt 学习之路 2(74):线程和 QObject Qt 学习之路 2(74):线程和 QObject  豆子  2013年12月3日  Qt 学习之路 2  2 ...

  4. python基础03-循环结构及函数基础

    循环结构及函数基础 循环结构(for-in) 说明:也是循环结构的一种,经常用于遍历字符串.列表,元组,字典等 格式: for x in y: 循环体 执行流程:x依次表示y中的一个元素,遍历完所有元 ...

  5. web前端基础

    超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为了提供一种发布和接 ...

  6. Kibana6.x.x源码分析--如何自定义savedObjectType对象

    上篇说到了如何使用kibana自带的savedObjectType对象,现在我们来自定义一个自己的savedObjectType. 下面的截图是我自己模仿写的保存对象,以及如何在kibana插件中注册 ...

  7. React笔记:ref注意事项

    [一]使用ref必须用在[类型式的组件]才起作用,用在[函数式的组件]是无效的. 下面这个例子用在了[函数式的组件]上,所以是无效的: function MyFunctionalComponent() ...

  8. HDU_2102 A计划 【BFS】

    一.题目 HDU2102 二.题意分析 该题其实就是三位空间内的BFS,但比较简单的是,它设置了传送门,可以直接传送上去,需要注意的是 1.到了传送门的时候要重新考虑传送的点的三种情况. (1)若又是 ...

  9. 给小程序组件创建slot

    <!--comviewonents/juan/juan.wxml--> <view class="model-wrapper" hidden="{{vi ...

  10. linux驱动之设备模型

    linux 设备驱动模型 inux2.6提供了新的设备模型:总线.驱动.设备.基本关系简要的概括如下: 驱动核心可以注册多种类型的总线. 每种总线下面可以挂载许多设备.(通过kset devices) ...