java nio文件上传_java nio文件传输例子

使用nio传输文件需要注意的是会出现粘包和服务器端缓冲区满的情况。第一种情况,客户端发送30次数据,而服务器端只接收到18次的情况,这种情况出现主要是服务器端是以流的方式接收数据,它并不知道每次客户端传输数据的大小而造成的。第二种情况是服务器端缓冲区满,导致客户端数据传输失败,这种情况下,需要判断传输int send = client.write(sendBuffer)的send值,如果send值为0,则服务器端的数据缓冲区可能满了。

客户端实现代码:

package penngo.nio.file;

import java.io.FileInputStream;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.SocketChannel;

import java.util.Set;

public class FileClient {

private int port = 8000;

/* 发送数据缓冲区 */

private static ByteBuffer sendBuffer = ByteBuffer.allocate(1024);

/* 接受数据缓冲区 */

private static ByteBuffer revBuffer = ByteBuffer.allocate(1024);

private InetSocketAddress SERVER;

private static Selector selector;

private static SocketChannel client;

public FileClient(){

try{

SERVER = new InetSocketAddress("localhost", port);

init();

}

catch(Exception e){

e.printStackTrace();

}

}

private void init(){

try {

SocketChannel socketChannel = SocketChannel.open();

socketChannel.configureBlocking(false);

selector = Selector.open();

socketChannel.register(selector, SelectionKey.OP_CONNECT);

socketChannel.connect(SERVER);

while (true) {

selector.select();

Set keySet = selector.selectedKeys();

for (final SelectionKey key : keySet) {

if(key.isConnectable()){

client = (SocketChannel)key.channel();

client.finishConnect();

client.register(selector, SelectionKey.OP_WRITE);

}

else if(key.isWritable()){

sendFile(client);

}

}

keySet.clear();

}

} catch (Exception e) {

e.printStackTrace();

}

}

private void sendFile(SocketChannel client) {

FileInputStream fis = null;

FileChannel channel = null;

try {

//fis = new FileInputStream("E:\\1.txt");

//fis = new FileInputStream("E:\\1.rar");

fis = new FileInputStream("G:\\3.rar");

channel = fis.getChannel();

int i = 1;

int count = 0;

while((count = channel.read(sendBuffer)) != -1) {

sendBuffer.flip();

int send = client.write(sendBuffer);

System.out.println("i===========" + (i++) + " count:" + count + " send:" + send);

// 服务器端可能因为缓存区满,而导致数据传输失败,需要重新发送

while(send == 0){

Thread.sleep(10);

send = client.write(sendBuffer);

System.out.println("i重新传输====" + i + " count:" + count + " send:" + send);

}

sendBuffer.clear();

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

channel.close();

fis.close();

client.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

public static void main(String[] args){

new FileClient();

}

}

服务器端

package penngo.nio.file;

import java.io.FileOutputStream;

import java.net.InetSocketAddress;

import java.net.ServerSocket;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.util.Set;

public class FileServer {

private int port = 8000;

/* 发送数据缓冲区 */

private static ByteBuffer revBuffer = ByteBuffer.allocate(1024);

private static Selector selector;

private static FileOutputStream fout;

private static FileChannel ch;

public FileServer(){

try{

init();

}

catch(Exception e){

e.printStackTrace();

}

}

private void init() throws Exception{

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.configureBlocking(false);

ServerSocket serverSocket = serverSocketChannel.socket();

serverSocket.bind(new InetSocketAddress(port));

selector = Selector.open();

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("server start on port:" + port);

while (true) {

try {

selector.select();// 返回值为本次触发的事件数

Set selectionKeys = selector.selectedKeys();

for (SelectionKey key : selectionKeys) {

ServerSocketChannel server = null;

SocketChannel client = null;

int count = 0;

if (key.isAcceptable()) {

server = (ServerSocketChannel) key.channel();

System.out.println("有客户端连接进入=============)");

client = server.accept();

client.configureBlocking(false);

client.register(selector, SelectionKey.OP_READ);

fout = new FileOutputStream("G:\\" + client.hashCode() + ".rar");

ch = fout.getChannel();

} else if (key.isReadable()) {

client = (SocketChannel) key.channel();

revBuffer.clear();

count = client.read(revBuffer);

int k = 0;

// 循环读取缓存区的数据,

while(count > 0){

System.out.println("k=" + (k++) + " 读取到数据量:" + count);

revBuffer.flip();

ch.write(revBuffer);

fout.flush();

revBuffer.clear();

count = client.read(revBuffer);

}

if(count == -1){

client.close();

ch.close();

fout.close();

}

}

else if (key.isWritable()) {

System.out.println("selectionKey.isWritable()");

}

}

System.out.println("=======selectionKeys.clear()");

selectionKeys.clear();

} catch (Exception e) {

e.printStackTrace();

break;

}

}

}

public static void main(String[] args){

new FileServer();

}

}

你可能感兴趣的:(java,nio文件上传)