NIO:流(TCP)信道详解

news/2024/5/17 16:16:57 标签: java, Java, JAVA, nio, NIO, socket, Socket, SOCKET, tcp, TCP,

信道有两个变体:SOCKET.html" title=Socket>SocketChannelServerSOCKET.html" title=Socket>SocketChannel。像其对应的SOCKET.html" title=Socket>Socket一样,SOCKET.html" title=Socket>SocketChannel是相互连接的终端进行通信的信道。

SOCKET.html" title=Socket>SocketChannel:创建,连接和关闭

static SOCKET.html" title=Socket>SocketChannel open(SOCKET.html" title=Socket>SocketAddress remote)

static SOCKET.html" title=Socket>SocketChannel open()

boolean connect(SOCKET.html" title=Socket>SocketAddress remote)

boolean isConnected()

void close()

boolean isOpen()

SOCKET.html" title=Socket>Socket SOCKET.html" title=socket>socket()

调用SOCKET.html" title=Socket>SocketChannel的静态工厂方法open()可以创建一个实例。open()方法的第一种形式SOCKET.html" title=Socket>SocketAddress(见第2章)为参数,返回一个连接到指定服务器的SOCKET.html" title=Socket>SocketChannel实例。注意,该方法可能会无限期地阻塞下去。open()的无参数形式用于创建一个没有连接的SOCKET.html" title=Socket>SocketChannel实例,该实例可以通过调用connect()方法连接到指定终端。当使用完SOCKET.html" title=Socket>SocketChannel后,需要调用close()方法将其关闭。有一点很重要,即每个SOCKET.html" title=Socket>SocketChannel实例都"包裹"了一个基本JAVA.html" title=Java>Java SOCKET.html" title=Socket>Socket,并可以通过SOCKET.html" title=socket>socket()方法对该SOCKET.html" title=Socket>Socket进行访问。这就可以通过基本的SOCKET.html" title=Socket>Socket方法进行绑定、设置套接字选项等操作。一个SOCKET.html" title=Socket>SocketChannel的创建、连接和关闭的例子,见TCPEchoClientNonblocking.JAVA.html" title=java>java(第113-114页)。

 在创建并连接SOCKET.html" title=Socket>SocketChannel后,就可以调用该信道的读写方法进行I/O操作。 

SOCKET.html" title=Socket>SocketChannel:读和写

int read(ByteBuffer dst)

long read(ByteBuffer[] dsts)

long read(ByteBuffer[] dsts, int offset, int length)

int write(ByteBuffer src)

long write(ByteBuffer[] srcs)

long write(ByteBuffer[] srcs, int offset, int length) 

读操作的最基本形式以一个ByteBuffer为参数,并将读取的数据填入该缓冲区所有的剩余字节空间中。另一种形式以多个ByteBuffer为参数(ByteBuffer数组),并根据其在数组中的顺序,将读取的数据依次填入每个缓冲区的剩余字节空间中。这种方法称为散射式读,因为它将读入的字节分散到了多个缓冲区中。需要注意重要的一点,散射式读不一定会将所有缓冲区填满,这些缓冲区的总空间大小只是一个上限。

写操作的最基本形式以一个ByteBuffer为参数,并试图将该缓冲区中剩余的字节写入信道。另一种形式以一个ByteBuffer数组作为参数,并试图将所有缓冲区中的剩余字节都写入信道。这种方法称为聚集式写,因为它把多个缓冲区中的字节聚集起来,一起发送出去。读

写操作的例子见TCPEchoClientNonblocking.JAVA.html" title=java>javaTCPServerSelector.JAVA.html" title=java>java

与其对应的ServerSOCKET.html" title=Socket>Socket一样,ServerSOCKET.html" title=Socket>SocketChannel是用来侦听客户端连接的信道。

ServerSOCKET.html" title=Socket>SocketChannel: 创建,接受和关闭

static ServerSOCKET.html" title=Socket>SocketChannel open()

ServerSOCKET.html" title=Socket>Socket SOCKET.html" title=socket>socket()

SOCKET.html" title=Socket>SocketChannel accept()

void close()

boolean isOpen()

调用静态工厂方法open()可以创建一个ServerSOCKET.html" title=Socket>SocketChannel实例。每个实例都包裹了一ServerSOCKET.html" title=Socket>Socket实例,并可以通过SOCKET.html" title=socket>socket()方法对其访问。正如前面的例子所表明的,必须通过访问底层的ServerSOCKET.html" title=Socket>Socket实例来实现绑定指定端口,设置套接字选项等操作。在创建了信道实例并绑定端口后,就可以调用accept()方法来准备接收客户端的连接请求。连接成功则返回一个新的已连接的SOCKET.html" title=Socket>SocketChannel。在用完ServerSOCKET.html" title=Socket>SocketChannel后,需要调用close()方法将其关闭。使用ServerSOCKET.html" title=Socket>Socket的例子见TCPServerSelector.JAVA.html" title=java>java(第116-117页)。

如前文提到的那样,阻塞式信道除了能够(必须)与Buffer一起使用外,对于普通套接字来说几乎没有优点。因此,可能总是需要将信道设置成非阻塞式的。 

SOCKET.html" title=Socket>SocketChannel, Server SOCKET.html" title=Socket>SocketChannel:设置阻塞行为

SelectableChannel configureBlocking(boolean block)

boolean isBlocking()

通过调用configureBlocking(false)可以将SOCKET.html" title=Socket>SocketChannelServerSOCKET.html" title=Socket>SocketChannel设置为非阻塞模式。configureBlocking()方法将返回一个SelectableChannel,它是SOCKET.html" title=Socket>SocketChannelServerSOCKET.html" title=Socket>SocketChannel父类。 

考虑为SOCKET.html" title=Socket>SocketChannel设置连接的情况。如果传给SOCKET.html" title=Socket>SocketChannel的工厂方法open()一个远程地址,对该方法的调用则将阻塞等待,直到成功建立了连接。要避免这种情况,可以使open()方法的无参数形式,配置信道为非阻塞模式,再调用connect()方法,指定远程终端地址。如果在没有阻塞的情况下连接已经建立,connect()方法返回true;否则需要有检查套接字是否连接成功的方法。

SOCKET.html" title=Socket>SocketChannel:测试连接性

boolean finishConnect()

boolean isConnected()

boolean isConnectionPending()

对于非阻塞SOCKET.html" title=Socket>SocketChannel来说,一旦已经发起连接,底层套接字可能即不是已经连接,又不是没有连接,而是连接"正在进行"。由于底层协议的工作机制(见第6章),套接字可能会在这个状态一直保持下去。finishConnect()方法可以用来检查在非阻塞套接字上试图进行的连接的状态,还可以在阻塞套接字建立连接的过程中阻塞等待,直到连接成功建立。例如,你可能需要将信道配置成非阻塞模式,通过connect()方法发起连接,做完一些其他工作后,又将信道配置成阻塞模式,然后调用finishConnect()方法等待连接建立完成。或者可以让信道保持在非阻塞模式,并反复调用finishConnect()方法,如TCPEchoClientNonblocking.JAVA.html" title=java>java中所示。

isConnected()用于检查套接字是否已经建立了连接,从而避免在进行其他操作时抛出NotYetConnectedException异常(如调在用read()write()时)。还可以使用isConnectionPending()方法来检查是否有连接在该信道上发起。知道是否有连接发起是必要的,因为如果没有的话,finishConnect()方法将抛出NoConnectionPendingException异常。

 

相关下载:

JAVA.html" title=Java>Java_TCPIP_SOCKET.html" title=Socket>Socket编程(doc)

http://download.csdn.net/detail/undoner/4940239

 

文献来源:

LSOFT.CN(琅软中国)  


http://www.niftyadmin.cn/n/1853208.html

相关文章

ATM源码

package atm;//张秋亮,信1705-3,20173529 public class Account { private String accountID; private String accountname; private String operatedate; private int operatetype; private String accountpassword; private int accountbalance; priv…

java读取jar包中resource下的图片

读取jar包或者war包中的文件时,只能使用流,不能使用new File Resource resource new ClassPathResource("topo_img" File.separator "a.png");

《那些年啊,那些事——一个程序员的奋斗史》十四(完结)

125 距离离职交接的一个月时间还剩几天,本来应该是平淡无事的,却没想到最后还是波澜四起。昨天下班前,公司突然停了电。这本是件普通得不能再普通的事情,可没想到过了一会来电了,或许是波峰电压太大,或许是…

报sslSocketFactory(SSLSocketFactory) not supported on JDK 9+

使用OkHttpClient的时候,jdk版本1.8.0_151启动不会报错,但jdk版本1.8.0_202启动就会报错,应该是OkHttpClient jdk小版本号高了不行,修改代码如下: public class SSLSocketClient {//获取这个SSLSocketFactorypublic s…

院校-美国:麻省理工学院(MIT)

ylbtech-院校-美国:麻省理工学院(MIT)麻省理工学院(Massachusetts Institute of Technology),简称麻省理工(MIT),坐落于美国马萨诸塞州波士顿都市区剑桥市,是…

NIO:Selector 详解

示例程序TCPEchoServerSelector中展示了Selector的基本用法。在此,我们将对其进行更加详细的介绍。 Selector: 创建和关闭 static Selector open() boolean isOpen() void close() 调用Selector的open()工厂方法可以创建一个选择器实例。选择器的状态是"打开&q…

NIO:数据报(UDP)信道

数据报(UDP)信道 Java的NIO包通过DatagramChannel类实现了数据报(UDP)信道。与我们之前看到的其他形式的SelectableChannel一样,DatagramChannel在DatagramSocket上添加了选择和非阻塞行为,以及基于缓冲区的…

Python学习--面向对象编程

一、编程范式 编程范式:按照什么方式来去编程,去实现一个功能。举个例子:做饭可以用电磁炉,也可以用燃气灶。不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,两种最重要的编程范式分别是面向过程…