博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java nio文件传输例子
阅读量:6159 次
发布时间:2019-06-21

本文共 5224 字,大约阅读时间需要 17 分钟。

  hot3.png

使用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(); }}

转载于:https://my.oschina.net/penngo/blog/121269

你可能感兴趣的文章
实战2——Hadoop的日志分析
查看>>
利用FIFO进行文件拷贝一例
查看>>
Ecshop安装过程中的的问题:cls_image::gd_version()和不支持JPEG
查看>>
resmgr:cpu quantum等待事件
查看>>
一个屌丝程序猿的人生(六十六)
查看>>
Java 编码 UTF-8
查看>>
SpringMVC实战(注解)
查看>>
关于静态属性和静态函数
查看>>
进程的基本属性:进程ID、父进程ID、进程组ID、会话和控制终端
查看>>
spring+jotm+ibatis+mysql实现JTA分布式事务
查看>>
MyBatis启动:MapperStatement创建
查看>>
调查问卷相关
查看>>
eclipse启动无响应,老是加载不了revert resources,或停留在Loading workbench状态
查看>>
1. Git-2.12.0-64-bit .exe下载
查看>>
怎样关闭“粘滞键”?
查看>>
[转]React 教程
查看>>
拓扑排序介绍
查看>>
eclipse打开工作空间(workspace)没有任务反应
查看>>
使用Sybmol模块来构建神经网络
查看>>
字符串去分割符号
查看>>