java aio复制文件_java socket实现文件传输分别基于BIO、NIO、AIO实现

为了加强对socket及java IO流编程的回顾,本文作了一个文件传输的实例。针对java不同对IO流的不同实现,本文也分别基于BIO、NIO、AIO实现三种传输,同时本文采用了缓冲输入/输出流来包装输出流,再采用数据输入/输出输出流包装缓冲流,加快传输的速度。最后本文基于大文件对三种方式基本传输效率对比。对于每一种传输方式分别实现服务端和客户端,并通过服务端发送文件到客户端,(同理可以实现客户端到服务器端的文件发送)

1、基于BIO的文件发送实现

服务端:BIOServer.java

package zmx.socket.filethransfer.bio;

import java.io.BufferedInputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

/**

* 本例实现基于BIO的Socket文件传输,客户端连接服务器后,服务器发送一个文件到客户端,

* 客户端接受文件,保存到本地。(同理可实现客户端向服务器的文件发送)

*

* 本类是服务端:实现接受连接和发送文件

* @author zhangwenchao

*/

public class BIOServer {

public static final int port=8821;

public static final int bufferSize = 8192;

public void serverStart(){

Socket s =null; //连接

try {

ServerSocket ss = new ServerSocket(port);//初始化ServerSocket

File f = new File("E:\\1.jpg");

System.out.println("要发送的文件为:"+f.getName()+" 文件大小:"+f.length());

while(true){//不断循环接受客户端请求

System.out.println("服务器正在监听端口:"+port+"...");

// public Socket accept() throws IOException

// 侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。

s = ss.accept(); //建立连接

System.out.println("Socket连接已经建立成功!");

//Socket输入流: 读取客户端发送过来的数据

DataInputStream dis = new DataInputStream(new BufferedInputStream(s.getInputStream()));

byte message = dis.readByte();

System.out.println(message);

//文件输入流:读取文件

DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));

//Socket输出流: 发送文件

DataOutputStream dos = new DataOutputStream(s.getOutputStream());

//将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java 4th里有现成的代码。

dos.writeUTF(f.getName());

dos.flush();

dos.writeLong((long) f.length());

dos.flush();

byte[] buf = new byte[bufferSize];

int len = 0;

while((len=fis.read(buf))!=-1){

dos.write(buf, 0, len);

}

dos.flush();

// 注意关闭socket链接哦,不然客户端会等待server的数据过来,

// 直到socket超时,导致数据不完整。

fis.close();

s.close();

System.out.println("文件传输完成");

}

} catch (IOException e) {

e.printStackTrace();

System.out.println("网络连接出现异常!");

}

}

public static void main(String arg[]) {

new BIOServer().serverStart();

}

}

客户端:BIOSocketUti.java+BIOClient.java

BIOSocketUtil.java

package zmx.socket.filethransfer.bio;

import java.io.BufferedInputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.net.Socket;

/**

* Socket连接工具

* @author zhangwenchao

*

*/

public class BIOSocketUtil{

/**

* 创建socket连接

* @throws Exception

* exception

*/

public static Socket CreateConnection(String ip, int port) throws Exception {

try {

Socket socket = new Socket(ip, port);

return socket;

} catch (Exception e) {

e.printStackTrace();

throw e;

} finally {

}

}

/**

* 发送一条信息,通知服务器本机的操作系统类型

* @param sendMessage 0x1:windows 0x2:unix 0x3:Linux

* @throws Exception

*/

public static void sendMessage(Socket socket,String sendMessage) throws Exception {

DataOutputStream outputStream = null;

try {

outputStream = new DataOutputStream(socket.getOutputStream());

if (sendMessage.equals("Windows")) {

outputStream.writeByte(0x1);

outputStream.flush();

return;

}

if (sendMessage.equals("Unix")) {

outputStream.writeByte(0x2);

outputStream.flush();

return;

}

if (sendMessage.equals("Linux")) {

outputStream.writeByte(0x3);

outputStream.flush();

} else {

outputStream.writeUTF(sendMessage);

outputStream.flush();

}

} catch (Exception e) {

System.out.println("发送消息错误" + "\n");

e.printStackTrace();

if (outputStream != null)

outputStream.close();

throw e;

} finally {

}

}

/**

* 获取输入流

* @return

* @throws Exception

*/

public static DataInputStream getMessageStream(Socket socket) throws Exception {

try {

DataInputStream inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

return inputStream;

} catch (Exception e) {

e.printStackTrace();

throw e;

} finally {

}

}

/**

* 关闭连接

*/

public static void shutDownConnection(Socket socket) {

try {

if (socket != null){

socket.close();

}

} catch (Exception e) {

}

}

}

BIOClient.java

package zmx.socket.filethransfer.bio;

import java.io.BufferedOutputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileOutputStream;

import java.net.Socket;

/**

* 客户端:发送一条消息 通知服务器本地操作系统类型,然后接受服务器发送的文件

* @author zhangwenchao

*

*/

public class BIOClient {

public static final int bufferSize = 8192;

private static void getFileMessage(Socket socket) {

if (socket == null)

return;

DataInputStream inputStream = null;

try {

inputStream = BIOSocketUtil.getMessageStream(socket); //根据socket获取输入流

} catch (Exception e) {

System.out.print("接收消息缓存错误\n");

return;

}

try {

//本地保存路径,文件名会自动从服务器端继承而来。

String savePath = "E:\\local\\";

byte[] buf = new byte[bufferSize];

int passedlen = 0; //统计收到的数据

//1、读取文件名

savePath += inputStream.readUTF();

//根据文件名新建一个文件输出流

DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savePath)));

//2、读取文件长度

long fileLength = inputStream.readLong();

System.out.println("文件的长度为:" + fileLength + "\n");

System.out.println("开始接收文件..." + "\n");

//3、读取文件内容

int len = 0;

while((len=inputStream.read(buf))!=-1){

passedlen += len;

//下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比

System.out.println("文件接收了" + (passedlen * 100/ fileLength) + "%\n");

fileOut.write(buf, 0, len);

}

System.out.println("接收完成,文件存为" + savePath + "\n");

fileOut.close();

} catch (Exception e) {

System.out.println("接收消息错误" + "\n");

return;

}

}

public static void main(String arg[]) {

String ip = "localhost";// 设置成服务器IP

int port = 8821;

String sendMessage = "Windwos";

try {

Socket socket = BIOSocketUtil.CreateConnection(ip, port);

System.out.print("连接服务器成功!" + "\n");

BIOSocketUtil.sendMessage(socket, sendMessage); //发送数据

getFileMessage(socket); //获取数据

} catch (Exception e) {

System.out.print("连接服务器失败!" + "\n");

}

}

}

运行测试结果:

要发送的文件为:1.jpg 文件大小:917070 服务器正在监听端口:8821... Socket连接已经建立成功! 0 文件传输完成!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值