设计一个简单的文件传输程序,服务器接受文件,客户端发送文件,设计一个简单的文件传输协议,比如,先传输文件名,再传输文件大小,再传输文件内容。
这里的图明显指出了服务端要创建线程,不过客户端并没有表明使用多线程,要实现多个客户端的话,用while来创建也可以满足每个客户端与单独一个服务端一一对应的交互要求。当然客户端也可以再创建个线程,只要在run里面放那些操作就行了,然后main函数再创建多个子线程即可。
设计一下服务端:
package EXP2020.exp12;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @author JM
* @date 2020/5/27
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server;
Socket serverSocket = null;
int count = 0;
server = new ServerSocket(2020);//设置服务端要监听的端口号
System.out.println("正在等待客户接入...");
while (true) {
serverSocket = server.accept();//等待客户连接
count++;
System.out.println(count + "号客户已连接,地址是:" + serverSocket.getInetAddress());
if (serverSocket != null)
new newThread(serverSocket).start(); //为客户启动一个线程
else System.out.println("连接失败");
}
}
}
/**
* 创建定义服务端接收和反馈信息的线程类
*/
class newThread extends Thread {
Scanner scanner = new Scanner(System.in);
Socket socket;
DataOutputStream out = null;
DataInputStream in = null;
//定义构造函数初始化流对象
newThread(Socket t) {
socket = t;
try {
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
}
}
//重写run方法
public void run() {
try {
String fileName = in.readUTF();
out.writeUTF("收到文件名 " + fileName);
Thread.sleep(1000);
int fileLength = in.readInt();
out.writeUTF("收到文件长度为:" + fileLength);
Thread.sleep(1000);
System.out.println("请输入文件保存的名字");
String fileSaveName = scanner.nextLine();
File path = new File("D:\\...\\" + fileSaveName);
if (!path.exists()) path.createNewFile();//如果不存在目标文件,就创建它
//接收文件并保存
FileOutputStream serverFile = new FileOutputStream(path);
byte[] data = new byte[1024];
while ((in.read(data)) != -1) {
serverFile.write(data, 0, fileLength);//只接收长度为fileLength的内容
break;
}
serverFile.close();//接收完后关闭文件
out.writeUTF("文件接收成功");
in.readUTF();//此时用户结束,进入catch结束程序
} catch (Exception e) {
System.out.println("客户端已经断开连接,等待下一个客户连接......\n");
return;
} finally {
//最后处理关闭相应的流
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
设计一下客户端:
package EXP2020.exp12;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* @author JM
* @date 2020/5/27
*/
public class Client {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
while (true) {
Socket clientSocket = null;
DataInputStream in = null;
DataOutputStream out = null;
//连接到服务端,可以用户自己输入,这里直接给出ip和的端口号
clientSocket = new Socket("127.0.0.1", 2020);
in = new DataInputStream(clientSocket.getInputStream());
out = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("请输入要发送的文件名");
String fileName = scanner.next();
out.writeUTF(fileName);//将文件名传给服务端
String receive = in.readUTF();//接收服务端反馈信息
System.out.println(receive);
System.out.println("请输入发送文件长度");
int fileLength = scanner.nextInt();
out.writeInt(fileLength);//将文件长度传给服务端
receive = in.readUTF();//接收服务端反馈信息
System.out.println(receive);
//发送文件内容
String path = "D:\\...\\" + fileName;
FileInputStream clientFile = new FileInputStream(new File(path));
byte[] data = new byte[1024];
int len = -1;
while ((len = clientFile.read(data)) != -1) {
out.write(data, 0, len);//发送内容
}
receive = in.readUTF();//接收服务端收到文件的反馈信息
System.out.println(receive);
System.out.println("客户端结束\n");
//收到反馈后,客户端结束
clientFile.close();
in.close();
clientSocket.close();
}
}
}
该死的nextLine让我找了那么久的bug,。。。。最后还是默默改回了next。