问题描述
Server端:import java.net.*;import java.io.*;public class Server {// 服务器监听端口private int port;// 文件保存路径private String path;// 判断server是否启动private boolean started = false;public static void main(String[] args) {new Server(8888, "E:/").listen(8888);}// 初始化服务器端口及文件保存路径private Server(int port, String path) {this.port = port;this.path = path;}// 二进制转换为十进制public static int b2i(byte[] b) {int value = 0;for (int i = 0; i < 4; i++) {int shift = (4 - 1 - i) * 8;value += (b[i] & 0x000000FF) << shift;}return value;}public static long b2l(byte[] b) {long s = 0;long s0 = b[0] & 0xff;long s1 = b[1] & 0xff;long s2 = b[2] & 0xff;long s3 = b[3] & 0xff;long s4 = b[4] & 0xff;long s5 = b[5] & 0xff;long s6 = b[6] & 0xff;long s7 = b[7] & 0xff;s1 <<= 8;s2 <<= 16;s3 <<= 24;s4 <<= 8 * 4;s5 <<= 8 * 5;s6 <<= 8 * 6;s7 <<= 8 * 7;s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;return s;}// 主线程始终处于监听状态,等待客户端连接private void listen(int port) {Socket s = null;ServerSocket ss = null;try {ss = new ServerSocket(port);started = true;System.out.println("监听端口:" + port);while (started) {s = ss.accept();System.out.println("A client connected!");new Thread(new HandleThread(s)).start();}} catch (IOException e) {e.printStackTrace();}}// 处理接收文件并做相关处理的线程类private class HandleThread implements Runnable {Socket s = null;private HandleThread(Socket s) {this.s = s;}public void run() {String name = getName(s);System.out.println(name);String isOver = getFile(name, s);System.out.println(isOver);}// 1、先获取文件名,并按照文件名创建相应文件壳,用于储存文件内容private String getName(Socket s) {try {InputStream is = s.getInputStream();BufferedInputStream bis = new BufferedInputStream(is);byte[] buffer1 = new byte[4];bis.read(buffer1);int name_len = b2i(buffer1);System.out.println("s_name_len = " + name_len);// 开始获取文件名byte[] buffer2 = new byte[name_len];bis.read(buffer2);return new String(buffer2);} catch (IOException e) {return new String("接收过程出现故障!");}}// 2、开始接收文件private String getFile(String name, Socket s) {InputStream is = null;BufferedInputStream bis = null;FileOutputStream fos = null;BufferedOutputStream bos = null;File file = null;try {file = new File(path + "/" + name);if (!file.exists()) {file.createNewFile();}is = s.getInputStream();bis = new BufferedInputStream(is);fos = new FileOutputStream(file);bos = new BufferedOutputStream(fos);byte[] bytes = new byte[8];bis.read(bytes);long size = b2l(bytes);System.out.println("s_size = " + size);byte[] buffer = new byte[1024];long count = 0;while (count < size) {long num = bis.read(buffer);bos.write(buffer);count = count + num;}/*int a = -1;while ((a = bis.read()) != -1) {bos.write(a);}*/bos.flush();bos.close();return "文件 " + file.getName() + " 大小 " + file.length()+ "接收完成!";} catch (IOException e) {return "接收失败";} finally {try {if (bos != null) {bos.close();bos = null;}if (fos != null) {fos.close();fos = null;}if (bis != null) {bis.close();bis = null;}if (is != null) {is.close();is = null;}if (s != null) {s.close();s = null;}} catch (IOException e) {e.printStackTrace();}}}}}Clientimport java.net.*;import java.io.*;public class Client {// 服务器ip地址private String ipAdd;// 服务器监听端口号private int port;// 发送文件路径private String path;public static void main(String[] args) {new Client("127.0.0.1", 8888, "D:\把悲伤留给自己.mp3").connect();}public Client(String ipAdd, int port, String path) {this.ipAdd = ipAdd;this.port = port;this.path = path;}// 连接到服务器private void connect() {Socket s = null;OutputStream os = null;BufferedOutputStream bos = null;try {s = new Socket(ipAdd, port);os = s.getOutputStream();bos = new BufferedOutputStream(os);File file = new File(path);// 文件名String name = file.getName();// 文件大小long size = file.length();System.out.printf("%s%s%s%s%s", "Sending file ", name, " size ",size, " bytes to server...");// 先发送文件名到服务器boolean completed1 = sendName(name, bos);boolean completed2 = sendContent(file, bos);if (completed1 && completed2) {System.out.println("文件发送成功");} else {System.out.println("文件发送失败");}} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {System.out.println("文件未检测到");} finally {try {if (bos != null) {bos.close();bos = null;}if (os != null) {os.close();os = null;}} catch (IOException e) {}}}// 整型数据转换为byte数据方法public static byte[] i2b(int i) {return new byte[] { (byte) ((i >> 24) & 0xFF),(byte) ((i >> 16) & 0xFF), (byte) ((i >> 8) & 0xFF),(byte) (i & 0xFF) };}// long类型转成byte数组public static byte[] l2b(long number) {long temp = number;byte[] b = new byte[8];for (int i = 0; i < b.length; i++) {b[i] = new Long(temp & 0xff).byteValue();temp = temp >> 8; // 向右移8位}return b;}// 发送文件名长度以及文件名到服务器private boolean sendName(String name, BufferedOutputStream bos) {byte[] buffer = name.getBytes();int name_len = buffer.length;try {// 这就要求文件名长度不能长于65535,当然,这显然不太可能!!!bos.write(i2b(name_len));bos.write(buffer);bos.flush();return true;} catch (IOException e) {return false;}}// 发送文件内容到服务器private boolean sendContent(File file, BufferedOutputStream bos) {try {long size = file.length();// 先发送文件长度bos.write(l2b(size));FileInputStream fis = new FileInputStream(file);BufferedInputStream bis = new BufferedInputStream(fis);byte[] buffer = new byte[1024];long count = 0;// 一边读入,一边写出while (count < size) {long d = bis.read(buffer);count = count + d;bos.write(buffer);}bos.flush();return true;} catch (FileNotFoundException e) {System.out.println("未检测到发送文件!");return false;} catch (IOException e) {return false;}}} 问题补充:Server端发送的文件内容和Client端接收的文件内容大小不一致,服务器端接收到的数据比客户端发送的数据大
解决方案
// 一边读入,一边写出 while (count < size) { int d = bis.read(buffer); if(d== -1) { //over break; } count = count + d; bos.write(buffer, 0, d); } 1024可能没写满write(byte[] b, int off, int len)