Java NIO - Socket 通道
-
简述
Java NIO套接字通道是一个可选类型的通道,这意味着它可以使用选择器进行多路复用,用于面向流的数据流连接套接字。套接字通道可以通过调用其静态 open() 方法创建,前提是任何预先存在的套接字尚不存在。套接字通道是通过调用 open 方法创建的,但尚未连接。为了连接套接字通道,将调用connect() 方法。这里要提到的一点是,如果通道未连接,并且尝试尝试尝试任何 I/O 操作,则此通道将引发 NotYet连接异常。因此,在执行任何IO操作之前,必须确保通道已连接。一旦通道被连接,它就会保持连接状态,直到它被关闭。套接字通道的状态可以通过调用其 isConnected 方法来确定。套接字通道的连接可以通过调用其finishConnect() 方法来完成。连接操作是否正在进行中可以通过调用“连接挂起”方法来确定。默认情况下,套接字通道支持非阻塞连接。此外,它还支持异步关闭,这类似于 Channel 类中指定的异步关闭操作。套接字通道对于多个并发线程使用是安全的。它们支持并发读取和写入,尽管在任何给定时间最多可能有一个线程正在读取,并且最多一个线程可能正在写入。连接和 finishConnect 方法相互同步,并且在调用这些方法之一时尝试启动读取或写入操作将被阻止,直到该调用完成。 -
套接字通道的重要方法
-
bind(SocketAddress local) − 此方法用于将套接字通道绑定到作为此方法的参数提供的本地地址。
-
connect(SocketAddress remote) − 此方法用于将套接字连接到远程地址。
-
finishConnect() − 此方法用于完成连接套接字通道的过程。
-
getRemoteAddress() − 此方法返回通道套接字连接到的远程位置的地址。
-
isConnected() − 如前所述,此方法返回套接字通道的连接状态,即它是否连接。
-
open() 和 open((SocketAddress remote) − open 方法用于打开没有指定地址的套接字通道,而参数化开放方法为指定的远程地址打开通道并连接到它。这种方便的方法的工作方式就好像是调用 open() 方法,在生成的套接字通道上调用 connect 方法,远程传递它,然后返回该通道。
-
read(ByteBuffer dst) − 此方法用于通过套接字通道从给定缓冲区读取数据。
-
isConnectionPending() − 此方法指示此通道上是否正在进行连接操作。
-
-
例
下面的示例演示如何从 Java NIO 套接字通道发送数据。C:/Test/temp.txt
Hello World!
客户端:SocketChannelClient.java
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.EnumSet; public class SocketChannelClient { public static void main(String[] args) throws IOException { ServerSocketChannel serverSocket = null; SocketChannel client = null; serverSocket = ServerSocketChannel.open(); serverSocket.socket().bind(new InetSocketAddress(9000)); client = serverSocket.accept(); System.out.println("Connection Set: " + client.getRemoteAddress()); Path path = Paths.get("C:/Test/temp1.txt"); FileChannel fileChannel = FileChannel.open(path, EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE) ); ByteBuffer buffer = ByteBuffer.allocate(1024); while(client.read(buffer) > 0) { buffer.flip(); fileChannel.write(buffer); buffer.clear(); } fileChannel.close(); System.out.println("File Received"); client.close(); } }
输出
在服务器启动之前,运行客户端不会打印任何内容。服务器:SocketChannelServer.java
import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; import java.nio.file.Path; import java.nio.file.Paths; public class SocketChannelServer { public static void main(String[] args) throws IOException { SocketChannel server = SocketChannel.open(); SocketAddress socketAddr = new InetSocketAddress("localhost", 9000); server.connect(socketAddr); Path path = Paths.get("C:/Test/temp.txt"); FileChannel fileChannel = FileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(1024); while(fileChannel.read(buffer) > 0) { buffer.flip(); server.write(buffer); buffer.clear(); } fileChannel.close(); System.out.println("File Sent"); server.close(); } }
输出
运行服务器将打印以下内容。Connection Set: /127.0.0.1:49558 File Received