Java Nio 简明教程
Java NIO - Socket Channel
Java NIO 套接字通道是一种可选择类型通道,这意味着它可以使用选择器多路复用,用于面向流的数据流连接套接字。套接字通道可以通过调用其静态 open() 方法创建,前提是没有任何预先存在的套接字。套接字通道是通过调用 open 方法创建的,但尚未连接。为了连接套接字通道,需要调用 connect() 方法。这里需要注意的一点是,如果通道未连接并且试图尝试任何 I/O 操作,则此通道将抛出 NotYetConnectedException。因此,必须确保在执行任何 IO 操作之前通道已连接。一旦通道连接上,它将保持连接状态,直到它被关闭。可以通过调用其 isConnected 方法来确定套接字通道的状态。
Java NIO socket channel is a selectable type channel which means it can be multiplexed using selector, used for stream oriented data flow connecting sockets.Socket channel can be created by invoking its static open() method,providing any pre-existing socket is not already present.Socket channel is created by invoking open method but not yet connected.In order to connect socket channel connect() method is to be called.One point to be mentioned here is if channel is not connected and any I/O operation is tried to be attempted then NotYetConnectedException is thrown by this channel.So one must be ensure that channel is connected before performing any IO operation.Once channel is get connected,it remains connected until it is closed.The state of socket channel may be determined by invoking its isConnected method.
套接字通道的连接可以通过调用其 finishConnect() 方法完成。是否正在进行连接操作可以通过调用 isConnectionPending 方法来确定。默认情况下,套接字通道支持非阻塞连接。它还支持异步关闭,这类似于通道类中指定的异步关闭操作。
The connection of socket channel could be finished by invoking its finishConnect() method.Whether or not a connection operation is in progress may be determined by invoking the isConnectionPending method.By default socket channel supports non-blocking connection.Also it support asynchronous shutdown, which is similar to the asynchronous close operation specified in the Channel class.
套接字通道可以安全地供多个并发线程使用。它们支持并发读和写,尽管最多只有一个线程可以读取,并且最多只有一个线程可以在任何给定时间写入。connect 和 finishConnect 方法彼此互斥同步,并且在其中一个方法的调用正在进行时尝试启动读取或写入操作将阻塞,直到该调用完成。
Socket channels are safe for use by multiple concurrent threads. They support concurrent reading and writing, though at most one thread may be reading and at most one thread may be writing at any given time. The connect and finishConnect methods are mutually synchronized against each other, and an attempt to initiate a read or write operation while an invocation of one of these methods is in progress will block until that invocation is complete.
Important methods of Socket channel
-
bind(SocketAddress local) − This method is used to bind the socket channel to the local address which is provided as the parameter to this method.
-
connect(SocketAddress remote) − This method is used to connect the socket to the remote address.
-
finishConnect() − This method is used to finishes the process of connecting a socket channel.
-
getRemoteAddress() − This method return the address of remote location to which the channel’s socket is connected.
-
isConnected() − As already mentioned this method returns the status of connection of socket channel i.e whether it is connected or not.
-
open() and open((SocketAddress remote) − Open method is used open a socket channel for no specified address while parameterized open method open channel for specified remote address and also connects to it.This convenience method works as if by invoking the open() method, invoking the connect method upon the resulting socket channel, passing it remote, and then returning that channel.
-
read(ByteBuffer dst) − This method is used to read data from the given buffer through socket channel.
-
isConnectionPending() − This method tells whether or not a connection operation is in progress on this channel.
Example
以下示例说明如何从 Java NIO SocketChannel 发送数据。
The following example shows the how to send data from Java NIO SocketChannel.
Client: 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();
}
}
Server: 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();
}
}