您的位置:首页 > 编程语言 > Java开发

java socket 实现c/s文件上传下载功能+注册登录

2017-12-16 17:28 796 查看
使用JAVA SOCKET实现c/s结构的通信程序,以实现客户端向服务器端的文件的上传以及服务器端向客户端的文件的下载。

实现思路:

1、在服务器端,创建SocketServer对象,监听某一端口,有连接请求则开一个线程处理这一请求

2、在客户端,根据服务器的ip地址以及端口号,创建socket连接,并通过此连接传送数据以及信号

实现效果:

①首先打开服务器程序:



②打开客户端程序,输入服务器ip,这里由于都运行在本地,输入127.0.0.1:



③客户端启动,显示选择菜单:



④选择1注册开始注册,注册结束后在服务器端会添加用户,客户端回到菜单:



⑤选择2登录开始使用刚才注册的帐号登录,登录成功后进入子菜单:



⑥以上过程在服务器端都有记录:



⑦客户端中在子菜单选择1上传文件,输入要上传的文件的路径(这里使用绝对路径,也可以使用相对路径):



⑧客户端上传文件,需要服务器端的同意:



⑨若不同意客户端的文件上传,则取消:



⑩客户端也会收到文件无法上传的通知,并且再次进入菜单:



十一、再次上传文件,这次服务器端同意文件上传,则文件会被保存到upload目录下:



十二、文件上传成功:



十三、在菜单中选择下载文件,会把服务器端upload文件夹下的文件罗列出来



十四、选择需要下载的文件,下载完成,文件保存在客户端的download文件夹中:



十五、上传下载的文件:









源码如下:

(服务器端程序)

package socket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

//用户类
class User {
public String username;
public String password;
public List<String> uploadFiles; // 存储上传过的文件名称
}

/**
* 服务器端程序
*
* @author Charles
*
*/
public class Server {
public static final int PORT = 12345;// 监听的端口号
// 账户列表
public static List<User> userList = new ArrayList<User>();

public static void main(String[] args) {
System.out.println("-------------------服务器启动------------------\n");
Server server = new Server();
server.init();
}

public void init() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
// 一旦有堵塞, 则表示服务器与客户端获得了连接
Socket client = serverSocket.accept();
// 处理这次连接
new HandlerThread(client);
}
} catch (Exception e) {
System.out.println("服务器异常: " + e.getMessage());
}
}

// 处理数据传输的线程
private class HandlerThread implements Runnable {
private Socket socket;

public HandlerThread(Socket client) {
socket = client;
new Thread(this).start();
System.out.println("调用一次处理线程");
}

public void run() {
try {
// 读取客户端数据的流
DataInputStream input = new DataInputStream(socket.getInputStream());
// 向客户端回复信息的流
DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// 接收客户端的选项
String clientInputStr = input.readUTF();

switch (clientInputStr) {
case "申请注册": {
String usernamepassword = input.readUTF(); // 获取注册的信息
String[] strs = usernamepassword.split("#");
// 根据上传的注册信息添加用户
User user = new User();
user.username = strs[0];
user.password = strs[1];
user.uploadFiles = new ArrayList<String>();
userList.add(user);
System.out.println("成功添加用户:" + user.username);
// System.out.println(userList);
out.writeUTF("注册成功!");
break;
} // #case "申请注册"

case "申请登录": {
String usernamepassword = input.readUTF(); // 获取注册的信息
String[] strs = usernamepassword.split("#");

System.out.println("客户端试图登录的帐号:" + strs[0]);

boolean canlogin = false;
User curuser = null;
for (User u : userList) {
if (u.username.equals(strs[0]) && u.password.equals(strs[1])) { // 可以登录
curuser = u;
canlogin = true;
break;
}
}

if (canlogin) { // 用户名和密码正确
out.writeBoolean(true); // 向客户端返回可以登录的信号
System.out.println("验证成功,已登录!\n");

boolean rei = true; // 循环接收传送文件
while (rei) {

// 接收到模块编号
clientInputStr = input.readUTF();
switch (clientInputStr) {
case "退出文件上传下载模块": { // 退出文件上传下载模块
rei = false;
break;
}
case "申请上传文件": { // 申请上传文件
clientInputStr = input.readUTF(); // 接收文件名
System.out.println("客户端上传的文件的文件名为:" + clientInputStr.substring(1) + " 是否接收此文件?(y/n)");
char receive = new Scanner(System.in)
d082
.nextLine().toCharArray()[0];
receive = Character.toLowerCase(receive);

if (receive == 'y') {
out.writeBoolean(true);
File f = new File("upload/" + clientInputStr
.substring(clientInputStr.lastIndexOf("/") + 1, clientInputStr.length()));
if (!f.getParentFile().exists()) {
f.getParentFile().mkdir();
}
if (!f.exists()) {
f.createNewFile();
}
FileOutputStream fos = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int flag = -1;
System.out.print("接收文件中...");

// 构造结束标志
byte[] endstr = "文件上传结束".getBytes("utf-8");
byte[] sendend = new byte[1024];
for (int i = 0; i < endstr.length; i++) {
sendend[i] = endstr[i];
}

// 当未读取到结束标志的时候就一直读取
while ((flag = input.read(buffer)) != -1
&& !new String(buffer, "utf-8").equals(new String(sendend, "utf-8"))) {
fos.write(buffer);
buffer = new byte[1024];
}
fos.close();
System.out.println("\n文件上传结束!\n");
} else {
System.out.println("已经拒绝客户端的服务器上传!");
out.writeBoolean(false);
}

continue;

}
case "申请下载文件": { // 申请下载文件
// 首先获取所有upload目录下的文件
File uploadDir = new File("upload");
if (uploadDir.exists()) { // 存在该目录
out.writeBoolean(true);
// 获取目录下所有文件
File[] files = uploadDir.listFiles();
String hint = "服务器上一共有" + files.length + "个文件\n0、退出下载\n";
for (int i = 0; i < files.length; i++) {
hint += (i+1)+"、"+files[i].getName()+"\n";
}
hint += "请输入需要下载的文件序号:";
out.writeUTF(hint);
int fileId=input.readInt();
if(fileId==0) {
continue;
}
out.writeUTF(files[fileId-1].getName());
// 构造结束标志
byte[] endstr = "文件下载结束".getBytes("utf-8");
byte[] sendend = new byte[1024];
for (int i = 0; i < endstr.length; i++) {
sendend[i] = endstr[i];
}

//获取文件输入流
FileInputStream fin = new FileInputStream(files[fileId-1]);
byte[] buffer = new byte[1024];
int readflag=-1;
System.out.println("正在向客户端发送文件...");
while((readflag=fin.read(buffer))!=-1) {
out.write(buffer);
}
fin.close();
out.write(sendend);
System.out.println("文件发送成功!\n");
continue;

} else { // 目录不存在,说明无法下载
out.writeBoolean(false);
}
continue;
}
default: {
break;
}

}

}

} else {
out.writeBoolean(false); // 向客户端返回不能登录的信号
System.out.println("验证失败不允许登录!\n");
}
} // #case "申请登录"

}// #switch
// 关闭流
out.close();
input.close();
} catch (Exception e) {
//e.printStackTrace();
System.out.println("服务器 run 异常: " + e.getMessage());
} finally {

if (socket != null) {
try {
socket.close();
} catch (Exception e) {
//e.printStackTrace();
socket = null;
System.out.println("服务端 finally 异常:" + e.getMessage());
}
}

}
}
}
}

(2)客户端程序

package socket;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Scanner;

public class Client {
public static String IP_ADDR = "localhost";// 服务器地址
public static final int PORT = 12345;// 服务器端口号

public static void main(String[] args) {
System.out.print("请输入要连接的服务器IP地址:");
Scanner in = new Scanner(System.in);
IP_ADDR = in.next(); // 获取服务器地址

System.out.println("\n------------------客户端启动--------------------\n");

boolean f1 = true; // 是否退出的标志变量
while (f1) {
System.out.print("菜单:\n1、注册\n2、登录\n3、退出\n请输入你的选择序号:");
int select = in.nextInt();
switch (select) {
case 1: { // 注册
Socket socket = null;
try {
System.out.println("------------------开始注册--------------------");
System.out.println("请输入用户名(不得包含\"#\"):");
String username = in.next();
if (username.contains("#")) { // 检查用户名是否合法
System.out.println("用户名不合法");
continue; // 跳出本次循环继续
}
System.out.println("请输入密码(不得包含\"#\"):");
String password = in.next();
if (password.contains("#")) { // 检查密码是否合法
System.out.println("密码不合法");
continue; // 跳出本次循环继续
}

// 创建一个流套接字并将其连接到指定主机上的指定端口号
socket = new Socket(IP_ADDR, PORT);
// 向服务器传递数据的流
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// 读取服务器端数据的流
DataInputStream input = new DataInputStream(socket.getInputStream());

out.writeUTF("申请注册");

String usernamepassword = username + "#" + password;
out.writeUTF(usernamepassword); // 传送注册信息

String msg = input.readUTF();

System.out.println("服务器端:" + msg + "\n");

} catch (IOException e) {
System.out.println("客户端注册异常:" + e.getMessage());
} finally {
// 关闭socket连接,释放资源
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
socket = null;
e.printStackTrace();
System.out.println("客户端 finally 异常:" + e.getMessage());
}
}
}
break;
}

case 2: { // 登录
Socket socket = null;
try {
System.out.println("\n------------------开始登录--------------------");
System.out.println("请输入用户名:");
String username = in.next();
System.out.println("请输入密码:");
String password = in.next();

String usernamepassword = username + "#" + password;

// 创建一个流套接字并将其连接到指定主机上的指定端口号
socket = new Socket(IP_ADDR, PORT);
// 向服务器传递数据的流
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// 读取服务器端数据的流
DataInputStream input = new DataInputStream(socket.getInputStream());

out.writeUTF("申请登录"); // 向服务器提交登录的请求,等待服务器响应
out.writeUTF(usernamepassword); // 向服务器上传登录信息以验证

boolean msg = input.readBoolean(); // 读取服务器响应的信号,判断是否可以登录

if (msg) { // 登陆成功
System.out.println("登录验证成功!\n");
// 开始进入上传下载文件模块
boolean f = true;
while (f) {
System.out.print("菜单:\n1、上传文件\n2、下载文件\n3、退出\n请输入你的选择序号:");
int choice = in.nextInt();
switch (choice) {
case 1: { // 上传文件
try {

out.writeUTF("申请上传文件"); // 向服务器提出上传文件的申请
// 向服务器端上传文件
System.out.println("\n请输入要上传的文件的路径(绝对路径或者相对于应用程序的相对路径):");
String uploadFileName = in.next();
// 先把文件名传给服务器
out.writeUTF("/" + uploadFileName);
System.out.println("等待服务器确认接收文件...");
boolean ret = input.readBoolean(); // 以utf编码读取
if (!ret) {
System.out.println("服务器端拒绝接收此文件!");
continue;
} else {
BufferedInputStream fin = new BufferedInputStream(
new FileInputStream(new File(uploadFileName)));
byte[] buffer = new byte[1024];
int flag = -1;
System.out.print("上传文件中...");
while ((flag = fin.read(buffer)) != -1) {
// 当未读取结束的时候就一直读取并且发送
out.write(buffer);
}
fin.close();
System.out.println("\n上传结束!\n");
}
// out.close(); //不能这样写因为会把socket也关闭
// socket.shutdownOutput(); //关闭输出流而不关闭socket ,最后发现也不能这样,因为output无法再次打开
// 构造结束标志
byte[] endstr = "文件上传结束".getBytes("utf-8");
byte[] sendend = new byte[1024];
for (int i = 0; i < endstr.length; i++) {
sendend[i] = endstr[i];
}
out.write(sendend);

} catch (Exception e) {
e.printStackTrace();
System.out.println("客户端异常:" + e.getMessage());
} finally {
continue;
}
}

case 2: { // 下载文件
out.writeUTF("申请下载文件"); // 向服务器提出下载文件的申请
boolean candown = input.readBoolean();
if (candown) {
System.out.println(input.readUTF());
int fileId = in.nextInt();
if (fileId == 0) {
out.writeInt(0);
continue;
} else {
out.writeInt(fileId);
// 获取文件名
String fname = input.readUTF();
// 接收文件
File df = new File("download/" + fname);
if (!df.getParentFile().exists()) {
df.getParentFile().mkdir();
}
if (!df.exists()) {
df.createNewFile();
}
FileOutputStream fos = new FileOutputStream(df);
byte[] buffer = new byte[1024];
int flag = -1;
System.out.print("下载文件中...");

// 构造结束标志
byte[] endstr = "文件下载结束".getBytes("utf-8");
byte[] sendend = new byte[1024];
for (int i = 0; i < endstr.length; i++) {
sendend[i] = endstr[i];
}

// 当未读取到结束标志的时候就一直读取
while ((flag = input.read(buffer)) != -1
&& !new String(buffer, "utf-8").equals(new String(sendend, "utf-8"))) {
fos.write(buffer);
buffer = new byte[1024];
}
fos.close();
System.out.println("文件下载结束!\n");
continue;
}
} else {
System.out.println("服务器上暂无文件可以下载!");
continue;
}
}

case 3: { // 退出上传下载
out.close();
input.close();
f = false;
System.out.println("客户端已退出文件上传下载模块。");
break;
}

default: {
out.close();
input.close();
break;
}

}
}

} else { // 登录失败
System.out.println("登录验证失败!\n");
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
socket = null;
//e.printStackTrace();
System.out.println("客户端 finally 异常:" + e.getMessage());
}
}
continue;
}

} catch (IOException e) {
System.out.println("客户端登录异常:" + e.getMessage());
} finally {
break;
}

}

case 3: {
System.out.println("--------------------关闭客户端--------------------");
f1 = false;
break;
}

default: {
break;
}

}
}

}
}
君科沃特
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息