- Java NIO Tutorial
- Java NIO - Home
- Java NIO - Overview
- Java NIO - Environment Setup
- Java NIO vs JAVA IO
- Java NIO - Channels
- Java NIO - File Channel
- Java NIO - DataGram Channel
- Java NIO - Socket Channel
- Java NIO - Server Socket Channel
- Java NIO - Scatter
- Java NIO - Gather
- Java NIO - Buffer
- Java NIO - Selector
- Java NIO - Pipe
- Java NIO - Path
- Java NIO - File
- Java NIO - AsynchronousFileChannel
- Java NIO - CharSet
- Java NIO - FileLock
- Java NIO Useful Resources
- Java NIO - Quick Guide
- Java NIO - Useful Resources
- Java NIO - Discussion
Java NIO - ServerSocket 通道
Java NIO 服务器套接字通道也是一个可选类型通道,用于连接套接字的面向流的数据流。服务器套接字通道可以通过调用其静态open()方法来创建,前提是任何预先存在的套接字尚未存在。服务器套接字通道是通过调用 open 方法创建但尚未绑定。为了绑定套接字通道,需要调用bind()方法。
这里需要提到的一点是,如果通道未绑定并且尝试进行任何 I/O 操作,则该通道会抛出 NotYetBoundException。因此,在执行任何 IO 操作之前必须确保通道已绑定。
通过调用 ServerSocketChannel.accept() 方法来侦听服务器套接字通道的传入连接。当accept()方法返回时,它返回一个带有传入连接的SocketChannel。因此,accept() 方法会阻塞,直到传入连接到达。如果通道处于非阻塞模式,则如果没有挂起的连接,accept 方法将立即返回 null。否则它将无限期地阻塞,直到有新的连接可用或发生 I/O 错误。
新通道的套接字最初是未绑定的;在接受连接之前,它必须通过其套接字的绑定方法之一绑定到特定地址。此外,新通道是通过调用系统范围默认 SelectorProvider 对象的 openServerSocketChannel 方法创建的。
就像套接字通道一样,服务器套接字通道可以使用read()方法读取数据。首先分配缓冲区。从 ServerSocketChannel 读取的数据存储到缓冲区中。其次,我们调用 ServerSocketChannel.read() 方法,它将从 ServerSocketChannel 读取数据到缓冲区中。read() 方法的整数值返回写入缓冲区的字节数
类似地,可以使用write()方法(使用 buffer 作为参数)将数据写入服务器套接字通道。通常在 while 循环中使用 write 方法,因为需要重复 write() 方法,直到 Buffer 没有更多字节可供写入。
Socket通道的重要方法
bind(SocketAddress local) - 此方法用于将套接字通道绑定到本地地址,该地址作为此方法的参数提供。
Accept() - 此方法用于接受与此通道的套接字建立的连接。
connect(SocketAddress remote) - 此方法用于将套接字连接到远程地址。
finishConnect() - 此方法用于完成连接套接字通道的过程。
getRemoteAddress() - 此方法返回通道套接字连接的远程位置的地址。
isConnected() - 正如已经提到的,此方法返回套接字通道的连接状态,即是否已连接。
open() - Open 方法用于打开没有指定地址的套接字通道。这种便捷方法的工作方式就像调用 open() 方法,在生成的服务器套接字通道上调用 connect 方法,将其传递到远程,然后返回该通道渠道。
read(ByteBuffer dst) - 此方法用于通过套接字通道从给定缓冲区读取数据。
setOption(SocketOption<T> name, T value) - 此方法设置套接字选项的值。
socket() - 此方法检索与此通道关联的服务器套接字。
validOps() - 此方法返回一个操作集,标识此通道支持的操作。服务器套接字通道仅支持接受新连接,因此此方法返回 SelectionKey.OP_ACCEPT。
例子
以下示例展示了如何从 Java NIO ServerSocketChannel 发送数据。
C:/测试/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