上一篇中讲到利用Socket和Java的IO流,去实现服务端和客户端互相发送和接收信息,这篇文章谈一谈如何实现文件(音乐、图片等)的发送和接收。
上文中实现了消息的传递,利用的是socket通信,使用到了Java中的IO流。而文件传输,只是将消息换成我们熟悉的文件,因此,我们只需要将传递消息改成传递文件即可,听上去好像挺简单的,那么如何实现将 消息—>文件 呢?
在Java基础中,我们知道File这个类可以用来表示一个文件(它不单单代表文件,也可表示文件目录),于是,我们并可以利用File这个类来实现我们的文件传输。
具体思路:
图片描述:
文字描述:
服务端:
- 打开文件
- 得到文件的输入流
- 得到客户端的输出流
- 将文件输入流写到客户端的输出流
- 结束操作,关闭流
客户端:
- 获取到服务端的输入流
- 创建文件,获得文件的输出流
- 将服务端的输入流写入到文件的输出流中
- 结束操作,关闭流
下面是具体的代码实现(只是简单的实现功能)。
//服务端
ServerSocket serverSocket = new ServerSocket(40000);
//阻塞等待客户端的连接
socket = serverSocket.accept();
//打开客户端的输出流
OutputStream os = socket.getOutputStream();
//将输出流进行封装
DataOutputStream dos = new DataOutputStream(os);
//打开文件,如音乐或图片
File realFile = new File(“文件的路径”);
//获取文件的输入流
FileInputStream fileInputStream = new FileInputStream(realFile);
/** 重点:
** 通过文件输入流获取数据,
** 再将数据通过客户端的输出流写到客户端
*/
byte[] buff = new byte[1024];
int length;
while ((length = fileInputStream.read(buff, 0, buff.length)) > 0) {
dos.write(buff, 0, length);
dos.flush();
}
...
关闭流操作
大致的代码如上,需要注意的地方:
- 上文末尾提到的readLine()方法导致线程阻塞问题。
- dos.write(buff, 0, length)方法一定要写明参数length,因为每次读取到的字节数不一定相同,所以一定要加上参数。而不应该使用dos.write(buff)。
客户端
客户端的实现是服务端的一个逆过程,即服务端将文件转换为流,客户端则将流转化为文件。
具体实现:
Socket socket = new Socket();
//连接服务器
socket.connect(new InetSocketAddress(IP, PORT), 5000); //PORT:端口号 等待时间:5000
//文件的存放地址,可自定义
String filePath = "/storage/emulated/0/xtransfer/";
File file = new File(filePath, "music.mp3");
//生成新的文件
try { file.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
//打开文件的输出流
FileOutputStream fos = new FileOutputStream(file);
//获取服务端的输入流
InputStream is = socket.getInputStream();
//将流进行包装
DataInputStream dis = new DataInputStream(is);
//将服务端通过流传入的数据写入到文件中去
byte[] buff = new byte[1024];
int length;
while ((length = dis.read(buff, 0, buff.length)) > 0) {
fos.write(buff, 0, length);
fos.flush();
}
...
关闭流操作
注意:
1. 上述流操作应该在子线程中进行操作,以避免UI线程遭到阻塞
2. 注意相关权限的申请,如果是6.0以上,请动态获取权限