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 ...