java SocketChannel实现文件传输 服务端用Selector 客户端和服务端怎么写
时间: 2023-11-04 12:05:50 浏览: 118
服务端的代码如下所示:
```java
import java.io.FileOutputStream;
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.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Iterator;
import java.util.Set;
public class Server {
private static final int BUFFER_SIZE = 1024;
private static final String SAVE_DIR = "path/to/save/directory";
public static void main(String[] args) throws IOException {
// 创建Selector和ServerSocketChannel
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8888));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server started...");
while (true) {
// 监听事件
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
// 接受客户端连接
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel clientChannel = serverChannel.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
System.out.println("Accepted connection from client: " + clientChannel.getRemoteAddress());
} else if (key.isReadable()) {
// 读取客户端发送的文件
SocketChannel channel = (SocketChannel) key.channel();
receiveFile(channel);
channel.close();
}
keyIterator.remove();
}
}
}
private static void receiveFile(SocketChannel channel) throws IOException {
// 创建保存文件的目录
Path saveDir = Path.of(SAVE_DIR);
if (!Files.exists(saveDir)) {
Files.createDirectories(saveDir);
}
// 创建文件输出流
String fileName = "received_file.txt";
Path filePath = saveDir.resolve(fileName);
FileOutputStream fos = new FileOutputStream(filePath.toFile());
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
int bytesRead;
while ((bytesRead = channel.read(buffer)) != -1) {
buffer.flip();
fos.getChannel().write(buffer);
buffer.clear();
}
fos.close();
System.out.println("File received: " + filePath);
}
}
```
客户端的代码如下所示:
```java
import java.io.FileInputStream;
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;
public class Client {
private static final int BUFFER_SIZE = 1024;
private static final String FILE_PATH = "path/to/file";
public static void main(String[] args) throws IOException {
// 创建Selector和SocketChannel
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_CONNECT);
socketChannel.connect(new InetSocketAddress("localhost", 8888));
while (true) {
// 监听事件
selector.select();
for (SelectionKey key : selector.selectedKeys()) {
if (key.isConnectable()) {
// 完成连接
SocketChannel channel = (SocketChannel) key.channel();
if (channel.finishConnect()) {
channel.register(selector, SelectionKey.OP_WRITE);
System.out.println("Connected to server: " + channel.getRemoteAddress());
}
} else if (key.isWritable()) {
// 发送文件给服务端
SocketChannel channel = (SocketChannel) key.channel();
sendFile(channel);
channel.close();
break;
}
}
selector.selectedKeys().clear();
}
}
private static void sendFile(SocketChannel channel) throws IOException {
// 创建文件输入流
FileInputStream fis = new FileInputStream(FILE_PATH);
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
int bytesRead;
while ((bytesRead = fis.getChannel().read(buffer)) != -1) {
buffer.flip();
channel.write(buffer);
buffer.clear();
}
fis.close();
System.out.println("File sent: " + FILE_PATH);
}
}
```
以上代码实现了基于SocketChannel的文件传输,其中服务端使用Selector进行事件监听和处理,客户端连接服务端后发送文件。请注意修改代码中的文件路径和保存目录路径适应你的实际情况。
阅读全文