- 浏览: 987886 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
SocketChannelImpl 解析一(通道连接,发送数据):http://donald-draper.iteye.com/blog/2372364
SocketChannelImpl 解析二(发送数据后续):http://donald-draper.iteye.com/blog/2372548
引言:
前一篇文章我们看了一下SocketChannelImpl发送多个字节序列的过程,先来回顾一下:
SocketChannelImpl写ByteBuffer数组方法,首先同步写锁,确保通道,输出流打开,连接建立委托给IOUtil,将ByteBuffer数组写到输出流中,这一过程为获取存放i个字节缓冲区的IOVecWrapper,遍历ByteBuffer数组m,将字节缓冲区添加到iovecwrapper的字节缓冲区数组中,如果ByteBuffer非Direct类型,委托Util从当前线程的缓冲区获取容量为j2临时DirectByteBuffer,并将ByteBuffer写到DirectByteBuffer,并将DirectByteBuffer添加到iovecwrapper的字节缓冲区(Shadow-Direct)数组中,将字节缓冲区的起始地址写到iovecwrapper,字节缓冲区的实际容量写到iovecwrapper;遍历iovecwrapper的字节缓冲区(Shadow-Direct)数组,将Shadow数组中的DirectByteBuffer通过Util添加到本地线程的缓存区中,并清除DirectByteBuffer在iovecwrapper的相应数组中的信息;最后通过
SocketDispatcher,将iovecwrapper的缓冲区数据,写到filedescriptor对应的输出流中。
今天我们来看一下接受数据
再来看SocketChannelImpl的读操作
从输入流读取字节序列,写到buffer,有几点要关注
1.
2.
3.
下面我们分别来看这几点:
1.
//确保通道,输入流打开,通道连接建立
2.
3.
这里循环的原因,线程读输入流,有可能因为某种原因被中断,中断位消除,继续读取输入流,写到buffer
//IOUtil
来看readIntoNativeBuffer方法
readIntoNativeBuffer方法中一点我们需要关注:
//从输入流读取k个字节到buffer
//NativeDispatcher
从NativeDispatcher的pread方法可以看出,当前JDK版本,还不支持pread操作,我的JDK版本为1.7.0.17。
//SocketDispatcher
至此读输入流到buffer,已经看完,首先同步读写,确保通道,输入流打开,通道连接建立,
清除原始读线程,获取新的本地读线程,委托IOUtil读输入流到buffer;IOUtil读输入流到buffer,首先确保buffer是可写的,否则抛出IllegalArgumentException,然后判断buffer是否为Direct类型,是则委托给readIntoNativeBuffer,否则通过Util从当前线程缓冲区获取一个临时的DirectByteBuffer,然后通过readIntoNativeBuffer读输入流数据到临时的DirectByteBuffer,这一个过程是通过SocketDispatcher的read方法实现,读写数据到DirectByteBuffer中后,将DirectByteBuffer中数据,写到原始buffer中,并将
DirectByteBuffer添加到添加临时DirectByteBuffer到当前线程的缓冲区,以便重用,
因为重新DirectByteBuffer为直接操作物理内存,频繁分配物理内存,将耗费过多的资源。
在来看从输入流读取数据,写到多个buffer:
从输入流读取数据,写到多个buffer,我们只需要关注下面这点
这里循环的原因,线程读输入流,有可能因为某种原因被中断,中断位消除,继续读取输入流,写到buffer;
//IOUtil
再来看IOUtil写buffer数组的关键点
//SocketDispatcher
至此我们把SocketChannelImpl从输入流读取数据,写到ByteBuffer数组的read方法看完,首先同步写锁,确保通道,连接建立,输入流打开,委托给IOUtil,从输入流读取数据写到ByteBuffer数组中;IOUtil首先获取存放i个字节缓冲区的IOVecWrapper,遍历ByteBuffer数组m,将buffer添加到iovecwrapper的字节缓冲区数组中,如果ByteBuffer非Direct类型,委托Util从当前线程的缓冲区获取容量为j2临时DirectByteBuffer,并将ByteBuffer写到DirectByteBuffer,并将DirectByteBuffer添加到iovecwrapper的字节缓冲区(Shadow-Direct)数组中,将字节缓冲区的起始地址写到iovecwrapper,字节缓冲区的实际容量写到iovecwrapper;遍历iovecwrapper的字节缓冲区(Shadow-Direct)数组,将Shadow数组中的DirectByteBuffer通过Util添加到本地线程的缓存区中,并清除DirectByteBuffer在iovecwrapper的相应数组中的信息;最后通过
SocketDispatcher,从filedescriptor对应的输入流读取数据,写到iovecwrapper的缓冲区中。
总结:
读输入流到buffer,首先同步读写,确保通道,输入流打开,通道连接建立,
清除原始读线程,获取新的本地读线程,委托IOUtil读输入流到buffer;IOUtil读输入流到buffer,首先确保buffer是可写的,否则抛出IllegalArgumentException,然后判断buffer是否为Direct类型,是则委托给readIntoNativeBuffer,否则通过Util从当前线程缓冲区获取一个临时的DirectByteBuffer,然后通过readIntoNativeBuffer读输入流数据到临时的DirectByteBuffer,这一个过程是通过SocketDispatcher的read方法实现,读写数据到DirectByteBuffer中后,将DirectByteBuffer中数据,写到原始buffer中,并将
DirectByteBuffer添加到添加临时DirectByteBuffer到当前线程的缓冲区,以便重用,因为重新DirectByteBuffer为直接操作物理内存,频繁分配物理内存,将耗费过多的资源。
从输入流读取数据,写到ByteBuffer数组的read方法,首先同步写锁,确保通道,连接建立,输入流打开,委托给IOUtil,从输入流读取数据写到ByteBuffer数组中;IOUtil首先获取存放i个字节缓冲区的IOVecWrapper,遍历ByteBuffer数组m,将buffer添加到iovecwrapper的字节缓冲区数组中,如果ByteBuffer非Direct类型,委托Util从当前线程的缓冲区获取容量为j2临时DirectByteBuffer,并将ByteBuffer写到DirectByteBuffer,并将DirectByteBuffer添加到iovecwrapper的字节缓冲区(Shadow-Direct)数组中,将字节缓冲区的起始地址写到iovecwrapper,字节缓冲区的实际容量写到iovecwrapper;遍历iovecwrapper的字节缓冲区(Shadow-Direct)数组,将Shadow数组中的DirectByteBuffer通过Util添加到本地线程的缓存区中,并清除DirectByteBuffer在iovecwrapper的相应数组中的信息;最后通过
SocketDispatcher,从filedescriptor对应的输入流读取数据,写到iovecwrapper的缓冲区中。
SocketChannelImpl 解析四(关闭通道等):http://donald-draper.iteye.com/blog/2372717
SocketChannelImpl 解析二(发送数据后续):http://donald-draper.iteye.com/blog/2372548
引言:
前一篇文章我们看了一下SocketChannelImpl发送多个字节序列的过程,先来回顾一下:
SocketChannelImpl写ByteBuffer数组方法,首先同步写锁,确保通道,输出流打开,连接建立委托给IOUtil,将ByteBuffer数组写到输出流中,这一过程为获取存放i个字节缓冲区的IOVecWrapper,遍历ByteBuffer数组m,将字节缓冲区添加到iovecwrapper的字节缓冲区数组中,如果ByteBuffer非Direct类型,委托Util从当前线程的缓冲区获取容量为j2临时DirectByteBuffer,并将ByteBuffer写到DirectByteBuffer,并将DirectByteBuffer添加到iovecwrapper的字节缓冲区(Shadow-Direct)数组中,将字节缓冲区的起始地址写到iovecwrapper,字节缓冲区的实际容量写到iovecwrapper;遍历iovecwrapper的字节缓冲区(Shadow-Direct)数组,将Shadow数组中的DirectByteBuffer通过Util添加到本地线程的缓存区中,并清除DirectByteBuffer在iovecwrapper的相应数组中的信息;最后通过
SocketDispatcher,将iovecwrapper的缓冲区数据,写到filedescriptor对应的输出流中。
今天我们来看一下接受数据
再来看SocketChannelImpl的读操作
public int read(ByteBuffer bytebuffer) throws IOException { if(bytebuffer == null) throw new NullPointerException(); Object obj = readLock;//获取读锁 JVM INSTR monitorenter ;//进入同步,try if(!ensureReadOpen())//确保通道,输入流打开,通道连接建立 return -1; int i = 0; begin(); int k; Object obj3; Exception exception; synchronized(stateLock) { if(isOpen()) break MISSING_BLOCK_LABEL_146; k = 0; } //清除读线程 readerCleanup(); end(i > 0 || i == -2); obj3 = stateLock; JVM INSTR monitorenter ; if(i > 0 || isInputOpen) goto _L2; else goto _L1 _L1: -1; obj; JVM INSTR monitorexit ; return; _L2: obj3; JVM INSTR monitorexit ; goto _L3 exception; obj3; JVM INSTR monitorexit ; throw exception; _L3: if(!$assertionsDisabled && !IOStatus.check(i)) throw new AssertionError(); obj; JVM INSTR monitorexit ; return k; //初始化本地读线程 readerThread = NativeThread.current(); obj1; JVM INSTR monitorexit ; int j; do //委托IOUtil从输入流读取字节序列,写到bytebuffer i = IOUtil.read(fd, bytebuffer, -1L, nd, readLock); while(i == -3 && isOpen()); ... }
从输入流读取字节序列,写到buffer,有几点要关注
1.
if(!ensureReadOpen())//确保通道,输入流打开,通道连接建立 return -1;
2.
//清除读线程 readerCleanup();
3.
do //委托IOUtil从输入流读取字节序列,写到bytebuffer i = IOUtil.read(fd, bytebuffer, -1L, nd, readLock); while(i == -3 && isOpen());
下面我们分别来看这几点:
1.
if(!ensureReadOpen())//确保通道,输入流打开,通道连接建立 return -1;
//确保通道,输入流打开,通道连接建立
private boolean ensureReadOpen() throws ClosedChannelException { Object obj = stateLock; JVM INSTR monitorenter ; if(!isOpen())//通道打开 throw new ClosedChannelException(); if(!isConnected())//连接建立 throw new NotYetConnectedException(); if(!isInputOpen)//输入流打开 return false; true; obj; JVM INSTR monitorexit ; return; Exception exception; exception; throw exception; }
2.
//清除读线程 readerCleanup();
private void readerCleanup() throws IOException { //同步通道状态锁,清除读线程,如果通道关闭则,执行清除工作 synchronized(stateLock) { readerThread = 0L; if(state == 3) kill();//这个后面再讲 } }
3.
do //委托IOUtil从输入流读取字节序列,写到bytebuffer i = IOUtil.read(fd, bytebuffer, -1L, nd, readLock); while(i == -3 && isOpen());
这里循环的原因,线程读输入流,有可能因为某种原因被中断,中断位消除,继续读取输入流,写到buffer
//IOUtil
static int read(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj) throws IOException { ByteBuffer bytebuffer1; //如果buffer为只读,则抛出IllegalArgumentException if(bytebuffer.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); //如果buffer为DirectBuffer,则委托给readIntoNativeBuffer if(bytebuffer instanceof DirectBuffer) return readIntoNativeBuffer(filedescriptor, bytebuffer, l, nativedispatcher, obj); //从当前线程缓存区获取临时的DirectByteBuffer bytebuffer1 = Util.getTemporaryDirectBuffer(bytebuffer.remaining()); int j; //委托readIntoNativeBuffer方法,读取输入流数据,到临时DirectByteBuffer int i = readIntoNativeBuffer(filedescriptor, bytebuffer1, l, nativedispatcher, obj); //读写模式切换 bytebuffer1.flip(); if(i > 0) //如果有数据被读取,则放到byteBuffer中 bytebuffer.put(bytebuffer1); j = i;//记录读取的字节数 //添加临时DirectByteBuffer到当前线程的缓冲区,以便重用, //因为重新DirectByteBuffer为直接操作物理内存,频繁分配物理内存,将耗费过多的资源。 Util.offerFirstTemporaryDirectBuffer(bytebuffer1); return j; Exception exception; exception; Util.offerFirstTemporaryDirectBuffer(bytebuffer1); throw exception; }
来看readIntoNativeBuffer方法
private static int readIntoNativeBuffer(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj) throws IOException { int i = bytebuffer.position(); int j = bytebuffer.limit(); //如果断言开启,buffer的position大于limit,则抛出断言错误 if(!$assertionsDisabled && i > j) throw new AssertionError(); //获取需要读的字节数 int k = i > j ? 0 : j - i; if(k == 0) return 0; int i1 = 0; //从输入流读取k个字节到buffer if(l != -1L) i1 = nativedispatcher.pread(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k, l, obj); else i1 = nativedispatcher.read(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k); //重新定位buffer的position if(i1 > 0) bytebuffer.position(i + i1); return i1; }
readIntoNativeBuffer方法中一点我们需要关注:
//从输入流读取k个字节到buffer
if(l != -1L) i1 = nativedispatcher.pread(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k, l, obj); else i1 = nativedispatcher.read(filedescriptor, ((DirectBuffer)bytebuffer).address() + (long)i, k);
//NativeDispatcher
int pread(FileDescriptor filedescriptor, long l, int i, long l1, Object obj) throws IOException { throw new IOException("Operation Unsupported"); }
从NativeDispatcher的pread方法可以看出,当前JDK版本,还不支持pread操作,我的JDK版本为1.7.0.17。
//SocketDispatcher
int read(FileDescriptor filedescriptor, long l, int i) throws IOException { return read0(filedescriptor, l, i); } static native int read0(FileDescriptor filedescriptor, long l, int i) throws IOException;
至此读输入流到buffer,已经看完,首先同步读写,确保通道,输入流打开,通道连接建立,
清除原始读线程,获取新的本地读线程,委托IOUtil读输入流到buffer;IOUtil读输入流到buffer,首先确保buffer是可写的,否则抛出IllegalArgumentException,然后判断buffer是否为Direct类型,是则委托给readIntoNativeBuffer,否则通过Util从当前线程缓冲区获取一个临时的DirectByteBuffer,然后通过readIntoNativeBuffer读输入流数据到临时的DirectByteBuffer,这一个过程是通过SocketDispatcher的read方法实现,读写数据到DirectByteBuffer中后,将DirectByteBuffer中数据,写到原始buffer中,并将
DirectByteBuffer添加到添加临时DirectByteBuffer到当前线程的缓冲区,以便重用,
因为重新DirectByteBuffer为直接操作物理内存,频繁分配物理内存,将耗费过多的资源。
在来看从输入流读取数据,写到多个buffer:
public long read(ByteBuffer abytebuffer[], int i, int j) throws IOException { //校验参数 if(i < 0 || j < 0 || i > abytebuffer.length - j) throw new IndexOutOfBoundsException(); Object obj = readLock;//获取读锁 JVM INSTR monitorenter ;//进入同步,try if(!ensureReadOpen())//确保通道打开,连接建立,输入流打开 return -1L; long l = 0L; begin();//与end协同,记录中断器,处理读操作过程中的中断问题 long l2; Object obj3; Exception exception; synchronized(stateLock) { if(isOpen()) break MISSING_BLOCK_LABEL_177; l2 = 0L; } //清除原始读线程 readerCleanup(); end(l > 0L || l == -2L); obj3 = stateLock; JVM INSTR monitorenter ; if(l > 0L || isInputOpen) goto _L2; else goto _L1 _L1: -1L; obj; JVM INSTR monitorexit ; return; _L2: obj3; JVM INSTR monitorexit ; goto _L3 exception; obj3; JVM INSTR monitorexit ; throw exception; _L3: if(!$assertionsDisabled && !IOStatus.check(l)) throw new AssertionError(); obj; JVM INSTR monitorexit ; return l2; //获取本地读线程 readerThread = NativeThread.current(); obj1; JVM INSTR monitorexit ; long l1; do //委托给IOUtil,从输入流读取数据,写到多个buffer l = IOUtil.read(fd, abytebuffer, i, j, nd); while(l == -3L && isOpen()); l1 = IOStatus.normalize(l); }
从输入流读取数据,写到多个buffer,我们只需要关注下面这点
do //委托给IOUtil,从输入流读取数据,写到多个buffer l = IOUtil.read(fd, abytebuffer, i, j, nd); while(l == -3L && isOpen());
这里循环的原因,线程读输入流,有可能因为某种原因被中断,中断位消除,继续读取输入流,写到buffer;
//IOUtil
static long read(FileDescriptor filedescriptor, ByteBuffer abytebuffer[], int i, int j, NativeDispatcher nativedispatcher) throws IOException { IOVecWrapper iovecwrapper; boolean flag; int k; //获取存放i个byteBuffer的IOVecWrapper iovecwrapper = IOVecWrapper.get(j); flag = false; k = 0; long l1; int l = i + j; for(int i1 = i; i1 < l && k < IOV_MAX; i1++) { ByteBuffer bytebuffer = abytebuffer[i1]; if(bytebuffer.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); int j1 = bytebuffer.position(); int k1 = bytebuffer.limit(); if(!$assertionsDisabled && j1 > k1) throw new AssertionError(); int j2 = j1 > k1 ? 0 : k1 - j1; if(j2 <= 0) continue; //将buffer添加到iovecwrapper的字节缓冲区数组中 iovecwrapper.setBuffer(k, bytebuffer, j1, j2); if(!(bytebuffer instanceof DirectBuffer)) { //获取容量为j2临时DirectByteBuffer ByteBuffer bytebuffer2 = Util.getTemporaryDirectBuffer(j2); //添加DirectByteBuffer到iovecwrapper的shadow buffer数组 iovecwrapper.setShadow(k, bytebuffer2); bytebuffer = bytebuffer2; j1 = bytebuffer2.position(); } //将字节缓冲区的起始地址写到iovecwrapper iovecwrapper.putBase(k, ((DirectBuffer)bytebuffer).address() + (long)j1); //将字节缓冲区的实际容量写到iovecwrapper iovecwrapper.putLen(k, j2); k++; } if(k != 0) break MISSING_BLOCK_LABEL_263; l1 = 0L; if(!flag) { for(int i2 = 0; i2 < k; i2++) { //获取iovecwrapper索引i2对应的字节序列副本 ByteBuffer bytebuffer1 = iovecwrapper.getShadow(i2); if(bytebuffer1 != null) //如果字节序列不为空,则添加到当前线程的缓存区中 Util.offerLastTemporaryDirectBuffer(bytebuffer1); //清除索引i2对应的字节序列在iovecwrapper中的字节序列数组,及相应副本数组的信息 iovecwrapper.clearRefs(i2); } } return l1; long l4; //委托给nativedispatcher,从filedescriptor对应的输入流读取数据,写到iovecwrapper的缓冲区中。 long l2 = nativedispatcher.readv(filedescriptor, iovecwrapper.address, k); }
再来看IOUtil写buffer数组的关键点
long l2 = nativedispatcher.readv(filedescriptor, iovecwrapper.address, k);
//SocketDispatcher
long readv(FileDescriptor filedescriptor, long l, int i) throws IOException { return readv0(filedescriptor, l, i); } static native long readv0(FileDescriptor filedescriptor, long l, int i) throws IOException;
至此我们把SocketChannelImpl从输入流读取数据,写到ByteBuffer数组的read方法看完,首先同步写锁,确保通道,连接建立,输入流打开,委托给IOUtil,从输入流读取数据写到ByteBuffer数组中;IOUtil首先获取存放i个字节缓冲区的IOVecWrapper,遍历ByteBuffer数组m,将buffer添加到iovecwrapper的字节缓冲区数组中,如果ByteBuffer非Direct类型,委托Util从当前线程的缓冲区获取容量为j2临时DirectByteBuffer,并将ByteBuffer写到DirectByteBuffer,并将DirectByteBuffer添加到iovecwrapper的字节缓冲区(Shadow-Direct)数组中,将字节缓冲区的起始地址写到iovecwrapper,字节缓冲区的实际容量写到iovecwrapper;遍历iovecwrapper的字节缓冲区(Shadow-Direct)数组,将Shadow数组中的DirectByteBuffer通过Util添加到本地线程的缓存区中,并清除DirectByteBuffer在iovecwrapper的相应数组中的信息;最后通过
SocketDispatcher,从filedescriptor对应的输入流读取数据,写到iovecwrapper的缓冲区中。
总结:
读输入流到buffer,首先同步读写,确保通道,输入流打开,通道连接建立,
清除原始读线程,获取新的本地读线程,委托IOUtil读输入流到buffer;IOUtil读输入流到buffer,首先确保buffer是可写的,否则抛出IllegalArgumentException,然后判断buffer是否为Direct类型,是则委托给readIntoNativeBuffer,否则通过Util从当前线程缓冲区获取一个临时的DirectByteBuffer,然后通过readIntoNativeBuffer读输入流数据到临时的DirectByteBuffer,这一个过程是通过SocketDispatcher的read方法实现,读写数据到DirectByteBuffer中后,将DirectByteBuffer中数据,写到原始buffer中,并将
DirectByteBuffer添加到添加临时DirectByteBuffer到当前线程的缓冲区,以便重用,因为重新DirectByteBuffer为直接操作物理内存,频繁分配物理内存,将耗费过多的资源。
从输入流读取数据,写到ByteBuffer数组的read方法,首先同步写锁,确保通道,连接建立,输入流打开,委托给IOUtil,从输入流读取数据写到ByteBuffer数组中;IOUtil首先获取存放i个字节缓冲区的IOVecWrapper,遍历ByteBuffer数组m,将buffer添加到iovecwrapper的字节缓冲区数组中,如果ByteBuffer非Direct类型,委托Util从当前线程的缓冲区获取容量为j2临时DirectByteBuffer,并将ByteBuffer写到DirectByteBuffer,并将DirectByteBuffer添加到iovecwrapper的字节缓冲区(Shadow-Direct)数组中,将字节缓冲区的起始地址写到iovecwrapper,字节缓冲区的实际容量写到iovecwrapper;遍历iovecwrapper的字节缓冲区(Shadow-Direct)数组,将Shadow数组中的DirectByteBuffer通过Util添加到本地线程的缓存区中,并清除DirectByteBuffer在iovecwrapper的相应数组中的信息;最后通过
SocketDispatcher,从filedescriptor对应的输入流读取数据,写到iovecwrapper的缓冲区中。
SocketChannelImpl 解析四(关闭通道等):http://donald-draper.iteye.com/blog/2372717
发表评论
-
文件通道解析二(文件锁,关闭通道)
2017-05-16 23:17 1084文件通道解析一(读写操作,通道数据传输等):http://do ... -
文件通道解析一(读写操作,通道数据传输等)
2017-05-16 10:04 1176Reference定义(PhantomRefere ... -
文件通道创建方式综述
2017-05-15 17:39 1083Reference定义(PhantomReference,Cl ... -
文件读写方式简单综述后续(文件,流构造)
2017-05-14 23:04 1502Java Socket通信实例:http://donald-d ... -
文件读写方式简单综述
2017-05-14 11:13 1150Java Socket通信实例:http://donald-d ... -
FileChanne定义
2017-05-12 23:28 957文件读写方式简单综述:http://donald-draper ... -
SeekableByteChannel接口定义
2017-05-11 08:43 1253ByteChannel,分散聚集通道接口的定义(SocketC ... -
FileChannel示例
2017-05-11 08:37 1009前面我们看过socket通道,datagram通道,以管道Pi ... -
PipeImpl解析
2017-05-11 08:41 948ServerSocketChannel定义:http://do ... -
Pipe定义
2017-05-10 09:07 923Channel接口定义:http://donald-drape ... -
NIO-Pipe示例
2017-05-10 08:47 921PipeImpl解析:http://donald-draper ... -
DatagramChannelImpl 解析四(地址绑定,关闭通道等)
2017-05-10 08:27 804DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析三(多播)
2017-05-10 08:20 1951DatagramChannelImpl 解析一(初始化):ht ... -
NIO-UDP实例
2017-05-09 12:32 1598DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析二(报文发送与接收)
2017-05-09 09:03 1423DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析一(初始化)
2017-05-08 21:52 1435Channel接口定义:http://donald-drape ... -
MembershipKeyImpl 简介
2017-05-08 09:11 940MembershipKey定义:http://donald-d ... -
DatagramChannel定义
2017-05-07 23:13 1241Channel接口定义:http://donald-drape ... -
MulticastChanne接口定义
2017-05-07 13:45 1160NetworkChannel接口定义:ht ... -
MembershipKey定义
2017-05-06 16:20 937package java.nio.channels; i ...
相关推荐
此外,Stream API也是1.8的一大亮点,它提供了处理集合的新方式,可以进行数据流的过滤、映射、归约等操作,大大简化了数据处理的代码。 在"jdk-5b86f66575b7"这个压缩包中,很可能包含了JDK 1.8的完整源码,包括...
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:574) at IceInternal.Network.doFinishConnect(Network.java:393) ... 6 more 这种报错是ICE服务端没有起来,telnet服务端ICE的端口不通...
Python自动化办公源码-34 Python批量新建文件夹并保存日志信息
粒子滤波算法在目标跟踪中的实践与源码解析集合:多套系统源码包括基于meanshift的应用、MATLAB实现及与卡尔曼滤波比较,粒子滤波(器)滤波(器)及应用源码集合目标跟踪提取图像特征 以下多套系统源码 1、基于meanshift和粒子滤波的目标跟踪代码 2、MATLAB编写的粒子滤波器的源代码 3、粒子滤波算法实例 4、粒子滤波mcmc介绍 5、粒子滤波算法 matlab(粒子滤波用于剩余寿命预测的实例代码 MATLAB语言编写 附有详细代码说明) 6、粒子滤波matlab代码(能够运行。 Pf粒子滤波实现的目标跟踪程序,可实现针对非高斯噪声情况下的跟踪) 7、粒子滤波代码(三个粒子滤波的演示程序,一个滤波,一个目标跟踪,一个机器人定位) 8、发个Matlab实现粒子滤波算法的程序 9、粒子滤波的简介和5中matlab程序仿真 10、粒子滤波代码与卡尔曼做比较(这是用于目标跟踪的粒子滤波代码, 用matlab编写的,很有借鉴性,一维情况下, 非高斯非线性,其中将扩展卡尔曼滤波与粒子滤波进行比较,更好的说明了粒子滤波的优越性) 11、EKF,UKF和PF粒子滤波的性能(对比分析EKF
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat
西门子PLC与三菱变频器通讯程序:触摸屏控制变频器实现精准频率调节与实时监控,西门子1200 PLC与3台三菱E700变频器通讯程序 器件:西门子1200 PLC,3台三菱E700变频器,西门子KTP700 Basic Pn触摸屏,昆仑通态触摸屏(带以太网),中途可以加路由器 控制方式:触摸屏与plc以太网通讯,PLC与变频器通讯485口相连 功能:触摸屏控制变频器设定频率,启停,读取输出频率,电压 说明:是程序,非硬件。 程序有注释,西门子触摸屏程序,昆仑通态程序,变频器设置,接线都有,一应俱全 ,核心关键词:西门子1200 PLC; 三菱E700变频器; 通讯程序; 触摸屏控制; 设定频率; 启停; 读取输出频率; 电压; PLC与变频器485口相连; 程序注释; 西门子触摸屏程序; 昆仑通态程序; 变频器设置; 接线。,基于西门子PLC与三菱变频器通讯的控制系统程序
Python自动化办公源码-35Python从Excel表中批量复制粘贴数据到新表
本项目为基于Spring Boot和Vue框架构建的出租车管理系统源码,总计包含118个文件,涵盖99个Java源文件、15个XML配置文件、1个Git忽略文件、1个JAR包文件以及1个Markdown文件。该系统采用Java语言开发,适用于出租车行业的智能化管理需求。
基于滑膜与PID控制的分布式电动汽车动态载荷分配与操稳控制优化策略,滑膜+pid+上层设计下层平均分配 优化分配 动态载荷分配,分布式电动汽车操稳控制 本研究在matlab simulink建立七自由度轮毂电机驱动汽车模型,使用滑膜联合控制以及pid控制实现转向过程中质心侧偏角,橫摆角速度,滑转率稳定性控制, ,关键词:滑膜控制; PID控制; 七自由度轮毂电机驱动汽车模型; 联合控制; 稳定性控制; 动态载荷分配; 操稳控制; 分布式电动汽车。,"基于滑膜与PID控制的分布式电动汽车操稳控制与动态载荷分配研究"
单相PWM整流器两种控制策略仿真研究:PR控制器与PI控制器的应用及性能分析,单相PWM整流器两种控制策略实现(交流220V-直流350V整流)仿真,分别采用直接电流控制(PR控制器)与dq控制(PI控制器)实现,两个仿真动稳态性能良好,附带仿真介绍文档,详细讲述仿真搭建过程,并附带参考文献与原理出处,内容详实,适合电力电子入门仿真参考。 ,核心关键词:单相PWM整流器;控制策略;直接电流控制(PR控制器);虚拟dq控制(PI控制器);仿真动稳态性能;仿真介绍文档;仿真搭建过程;参考文献;原理出处;电力电子入门仿真参考。,《单相PWM整流器仿真:直接电流与虚拟dq控制策略对比解析》
chromedriver-win64-125版本所有资源打包:125.0.6368.0 -125.0.6422.78之间的所有版本打包下载
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat
IEEE69节点系统Simulink仿真模型:潮流计算与故障分析及分布式电源影响观察,IEEE69节点系统Simulink仿真 1.基础功能:基于Matlab simulink平台搭建IEEE33节点仿真模型,对电力系统进行潮流计算 2.拓展功能: 可在该IEEE69节系统仿真模型上进行故障分析(短路,断线等),也可以在该模型上接入分布式电源,观察分布式电源接入对系统的影响。 ,IEEE69节点系统Simulink仿真; Matlab Simulink平台; 潮流计算; 故障分析; 分布式电源接入影响; 短路分析; 断线分析。,Matlab Simulink中IEEE 69节点系统仿真:功能扩展与分布式电源接入影响分析
2025最新人工智能与健康题库及答案.docx
蛇优化算法SO优化LSSVM的c和g参数在多输入单输出下的拟合预测建模——Matlab程序实现与结果展示,蛇优化算法SO优化支持向量机LSSVM的c和g参数做多输入单输出的拟合预测建模。 程序内注释详细直接替数据就可以使用。 程序语言为matlab。 程序直接运行可以出拟合预测图,迭代优化图,线性拟合预测图,多个预测评价指标。 PS:以下效果图为测试数据的效果图,主要目的是为了显示程序运行可以出的结果图,具体预测效果以个人的具体数据为准。 2.由于每个人的数据都是独一无二的,因此无法做到可以任何人的数据直接替就可以得到自己满意的效果。 ,蛇优化算法; SO优化; 支持向量机; LSSVM; c和g参数; 多输入单输出; 拟合预测建模; MATLAB程序; 拟合预测图; 迭代优化图; 线性拟合预测图; 预测评价指标。,基于蛇优化算法与SO优化的LSSVM多输入单输出预测建模及可视化工具
系统旨在为了帮助鸟类爱好者、学者、动物保护协会等群体更好的了解和保护鸟类动物。用户群体可以通过平台采集野外鸟类的保护动物照片和视频,甄别分类、实况分析鸟类保护动物,与全世界各地的用户,沟通交流。使用方法请参考文章:https://blog.csdn.net/m0_64027967/article/details/145266648
http和https的区别?【http和https有什么区别?实现网站https化-让网站更安全!简介】 内容概要: 本文为初学者提供了一个全面的学习指南,通过通俗易懂的语言,介绍了http和https的区别,以及如何实现网站https化。本文旨在帮助读者理解网站安全性的重要性,并掌握网站https化的实现方法。 适用人群: 本篇文章主要面向初学者,特别是那些对网络安全感兴趣的读者。它为读者提供了一个实用的指南,帮助他们了解网站安全的基本概念和方法。 使用场景及目标: 本篇文章适用于那些想要提高自己网站安全性的读者。它的目标是帮助读者理解https的作用,掌握实现网站https化的方法和步骤,从而保护自己的网站和用户的安全。 其他说明: 文章采用通俗易懂、口语化的语言风格,旨在让读者轻松理解并吸收内容。同时,文章还强调了实际操作的重要性,鼓励读者亲自动手实践,提高自己的网络安全技能。最后,文章鼓励读者保持积极的心态,将网络安全作为一项重要的技能进行学习和实践。
基于FATFS系统的STM32F407 SD卡升级Bootloader程序:自动检测与升级流程,stm32f407 SD卡升级 bootloader程序 基于sdio fatfs系统的stm32 bootloader程序 功能简介: 本程序使用fatfs系统读取bin文件。 开机后会自动检测sd卡,检测到sd卡后,再读取固定名称的bin文件,之后会对bin文件进行首包校验,判断该升级包的起始地址是否正确,正确的话,就循环读取bin文件并写入到flash中。 完成升级。 详细流程请看流程图 ,stm32f407; SD卡升级; bootloader程序; fatfs系统读取bin文件; 检测SD卡; 首包校验; 循环写入flash。,STM32F407 SD卡升级Bootloader程序:基于SDIO FATFS系统实现自动升级功能
Python自动化办公源码-16从Excel总表中分割10个部门的年假数据
大规模MIMO-D2D蜂窝网络中的下行传输速率研究.pdf