1. FileChannel写入文件
package com.mycom.test.nio;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* FileChannel写入文件
*
* @author guweiqiang
*/
public class TestFileChannelWrite {
public static void main(String[] args) {
try {
// 新建一个File对象
File file = new File("e:/writeData.txt");
// 将文件读取到文件输出流中
FileOutputStream outputStream = new FileOutputStream(file);
// 获取FileChannel通道对象
FileChannel fileChannel = outputStream.getChannel();
// 新建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
String testStr = "hello world!";
// 将内容写入到缓冲区
buffer.put(testStr.getBytes());
buffer.flip(); //此处必须要调用buffer的flip方法
// 将缓冲区内容写入到fileChannel通道
fileChannel.write(buffer);
// 关闭fileChannel通道
fileChannel.close();
// 关闭文件输出流
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. FileChannel读取文件
package com.mycom.test.nio;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* FileChannel读取文件
*
* @author guweiqiang
*/
public class TestFileChannelRead {
@SuppressWarnings("resource")
public static void main(String[] args) {
try {
// 新建一个RandomAccessFile对象
RandomAccessFile file = new RandomAccessFile("e:/readData.txt", "rw"); // rw表示以读写方式打开文件,r表示只读方式打开
// 获取FileChannel通道对象
FileChannel fileChannel = file.getChannel();
// 新建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 将fileChannel中的数据读取到buffer中
fileChannel.read(buffer);
// 再将buffer中的数据读取到String对象中
byte[] data = buffer.array();
String ss = new String(data).trim();
System.out.println(ss);
// 关闭fileChannel通道
fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(前提是存在以下文件:e:/readData.txt)
3. Server与Cilent通信
NIO 服务端:
package com.mycom.test.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
* NIO 服务端
*
* @author guweiqiang
*/
public class NIOServer {
// 通道管理器
private Selector selector;
/**
* 获取一个服务端通道ServerSocket,并进行初始化
*/
public void initServer(int port) throws IOException{
// 获取一个ServerSocket服务端通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
// 设置通道为非阻塞模式
serverChannel.configureBlocking(false);
// 绑定端口
serverChannel.socket().bind(new InetSocketAddress(port));
// 获取一个通道管理器
this.selector = Selector.open();
// 将通道管理器和通道进行绑定,并为该通道注册SelectionKey.OP_ACCEPT事件
// 当事件到达时,selector.select()就会返回;如果事件没有到达,则selector.select()就会一直阻塞
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}
/**
* 采用轮询的方式监听selector上是否有需要处理的事件,如果有则进行处理
*/
@SuppressWarnings("rawtypes")
public void listen() throws IOException{
System.out.println("服务端启动成功!");
// 轮询访问selector
while(true){
// 当有已注册的事件到达时,方法返回,否则就一直阻塞到有注册的事件到达为止
selector.select();
// 获取selector中选中项的迭代器,选中项为注册的事件
Iterator it = this.selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey key = (SelectionKey)it.next();
// 删除已选的key,防止重复处理
it.remove();
if(key.isAcceptable()){ // 有客户端请求连接的事件
// 获取服务端通道
ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
// 获取与客户端连接的通道
SocketChannel clientChannel = serverChannel.accept();
// 设置为非阻塞
clientChannel.configureBlocking(false);
// 给客户端发送消息
clientChannel.write(ByteBuffer.wrap(new String("hello client, i'm server!").getBytes("utf-8")));
// 在和客户端连接成功之后,为了可以接收到客户端的消息,需要给通道设置读权限
clientChannel.register(this.selector, SelectionKey.OP_READ);
} else if(key.isReadable()){ // 有读取事件发生
readKey(key);
}
}
}
}
/**
* 处理读取客户端发来的消息
*/
private void readKey(SelectionKey key) throws IOException {
// 服务器可读取消息:得到事件发生的Socket通道
SocketChannel channel = (SocketChannel)key.channel();
// 读取通道里的消息
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
byte[] data = buffer.array();
String receivedMsg = new String(data).trim();
System.out.println("服务端收到客户端发来的的消息:" + receivedMsg);
// 向通道写入消息
String sendMsg = "hello client!";
ByteBuffer outBuffer = ByteBuffer.wrap(sendMsg.getBytes("utf-8"));
channel.write(outBuffer);// 将消息回送给客户端
}
/**
* 启动服务端测试
*/
public static void main(String[] args) {
try {
NIOServer server = new NIOServer();
server.initServer(8000);
server.listen();
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO 客户端:
package com.mycom.test.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
* NIO 客户端
*
* @author guweiqiang
*/
public class NIOClient {
// 通道管理器
private Selector selector;
/**
* 获取一个客户端通道,并进行初始化
* @throws IOException
*/
public void initClient(String ip, int port) throws IOException{
// 获取一个Socket客户端通道
SocketChannel clientChannel = SocketChannel.open();
// 设置通道为非阻塞模式
clientChannel.configureBlocking(false);
// 获取一个通道管理器
this.selector = Selector.open();
// 客户端连接服务器
clientChannel.connect(new InetSocketAddress(ip, port));
// 将通道管理器和通道进行绑定,并为该通道注册SelectionKey.OP_CONNECT事件
clientChannel.register(selector, SelectionKey.OP_CONNECT);
}
/**
* 采用轮询的方式监听selector上是否有需要处理的事件,如果有则进行处理
*/
@SuppressWarnings("rawtypes")
public void listen() throws IOException{
// 轮询访问selector
while(true){
// 当有已注册的事件到达时,方法返回,否则就一直阻塞到有注册的事件到达为止
selector.select();
// 获取selector中选中项的迭代器,选中项为注册的事件
Iterator it = this.selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey key = (SelectionKey)it.next();
// 删除已选的key,防止重复处理
it.remove();
if(key.isConnectable()){ // 有连接事件发生
// 获取客户端通道
SocketChannel clientChannel = (SocketChannel)key.channel();
// 如果正在连接,则设置连接完成
if(clientChannel.isConnectionPending()){
clientChannel.finishConnect();
}
// 设置通道为非阻塞模式
clientChannel.configureBlocking(false);
// 给服务端发送消息
clientChannel.write(ByteBuffer.wrap(new String("hello server, i'm client!").getBytes("utf-8")));
// 在和服务端连接之后,为了可以接收到服务端的消息,需要给客户端设置读权限
clientChannel.register(selector, SelectionKey.OP_READ);
} else if(key.isReadable()){ // 有读取事件发生
this.readKey(key);
}
}
}
}
/**
* 处理读取服务端发来的消息
*/
private void readKey(SelectionKey key) throws IOException {
// 服务器可读取消息:得到事件发生的Socket通道
SocketChannel channel = (SocketChannel)key.channel();
// 读取通道里的消息
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
byte[] data = buffer.array();
String receivedMsg = new String(data).trim();
System.out.println("客户端收到服务端发来的消息:" + receivedMsg);
// 向通道写入消息
String sendMsg = "hello server!";
ByteBuffer outBuffer = ByteBuffer.wrap(sendMsg.getBytes("utf-8"));
channel.write(outBuffer);// 将消息回送给服务端
}
/**
* 启动客户端测试
*/
public static void main(String[] args) {
try {
NIOClient client = new NIOClient();
client.initClient("127.0.0.1", 8000);
client.listen();
} catch (IOException e) {
e.printStackTrace();
}
}
}
本文介绍了Java NIO技术中的FileChannel用于文件读写操作,并详细阐述了如何使用NIO实现服务端与客户端之间的通信。通过实例演示了如何创建、配置并监听Socket通道,以及如何在服务端和客户端之间发送和接收消息。
969

被折叠的 条评论
为什么被折叠?



