运行结果:

Socket实例之客户端向服务端数据库上传文件UI版_TCP编程

首先实现分析:

1用户注册
客户单选择‘用户注册’,提示要输入用户名,密码,确认密码,校验成功后将用户
信息保存到数据库,并提示数据库注册成功,请登录
2用户登录
客户端选择‘登录以后’后,提示输入用户名和密码,验证成功则提示上传文件
,验证失败则给出提示信息,并可以重新登录
3文件上传
客户端输入上传文件的路径,并读取文件数据,通过输出流发送到服务端,服务端接受
后将上传文件保持在数据库

所有类如图:

Socket实例之客户端向服务端数据库上传文件UI版_socket_02

cn.edu.xynu.entity包里面有两个实体类

分别是数据库中的用户内容和文件内容。

数据库中的两张表的设计如下图

Socket实例之客户端向服务端数据库上传文件UI版_Socket实例之客户端向服务端上传文件_03

Socket实例之客户端向服务端数据库上传文件UI版_TCP编程_04

User实体类。和数据库的user表内容一致

 

package cn.edu.xynu.entity;

import java.io.Serializable;

public class User implements Serializable{
/**
* 用户的实体类
*/
private static final long serialVersionUID = 4015036439904829095L;
private String username;
private String password;

public User() {
super();
// TODO Auto-generated constructor stub
}

public User(String username, String password) {
super();
this.username = username;
this.password = password;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

}

File实体类和数据库的File表内容一致

package cn.edu.xynu.entity;

import java.io.Serializable;

public class File implements Serializable{

/**
* 文件的实体类
*/
private static final long serialVersionUID = 1L;
private String fname;
private String username;
private byte[] fcontent;
public File() {
super();
// TODO Auto-generated constructor stub
}

public File(String fname, String username, byte[] fcontent) {
super();
this.fname = fname;
this.username = username;
this.fcontent = fcontent;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public byte[] getFcontent() {
return fcontent;
}
public void setFcontent(byte[] fcontent) {
this.fcontent = fcontent;
}

}

cn.edu.xynu.service包里主要是对业务的实现

 

FileService 类实现客户端文件向服务器数据库的上传

 

package cn.edu.xynu.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import cn.edu.xynu.entity.File;
import cn.edu.xynu.util.DBHelper;

/**
* @author scx
* 文件服务类
*/
public class FileService {
//上传文件
public boolean uploadFile(File file) {
Connection conn = null;
PreparedStatement ps = null;
conn = DBHelper.getConnection();
String sql = "insert into file (username,filename,filecontent) values(?,?,?)";
try {
ps = conn.prepareStatement(sql);
ps.setString(1, file.getUsername().trim());
ps.setString(2, file.getFname().trim());
ps.setBytes(3, file.getFcontent());
int n=ps.executeUpdate();
if(n>0){
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(conn!=null)
conn.close();
if(ps!=null)
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
}

UserService类主要实现用户的登录和注册

package cn.edu.xynu.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import cn.edu.xynu.entity.User;
import cn.edu.xynu.util.DBHelper;

/**
* @author scx
* 用户服务类
*/
public class UserService {
private Connection conn = null;
private PreparedStatement ps = null;
//检测账户在数据库是否存在
public boolean checkUser(User user) {
String username = user.getUsername();
String password = user.getPassword();
try {
conn = DBHelper.getConnection();
String sql = "select * from user where username =? and password=?";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
rs.last();
int n = rs.getRow();
if (n > 0) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (ps != null)
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
//在数据库中添加注册的用户
public boolean addUser(User user) {
String username = user.getUsername();
String password = user.getPassword();
try {
conn = DBHelper.getConnection();
String sql = "insert into user (username,password) values(?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
int x = ps.executeUpdate();
if (x > 0) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (ps != null)
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
}

然后cn.edu.xynu.socket包里面主要是socket编程的类

 

Client类实现与服务端的通信

 

package cn.edu.xynu.socket;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import cn.edu.xynu.util.CommandTranser;

/**
* @author scx
* 客户端
*/
public class Client {
public static Socket socket=null;
public static int port=8888;
public static String address="127.0.0.1";
//获得服务器的数据
public static CommandTranser getData() {
// TODO Auto-generated method stub
ObjectInputStream ois=null;
CommandTranser res=null;
try {
ois=new ObjectInputStream(Client.socket.getInputStream());
res=(CommandTranser) ois.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(ois!=null){
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return res;
}
//向服务器发送数据
public static void sendData(CommandTranser cmd) {
// TODO Auto-generated method stub
ObjectOutputStream oos=null;
try {
oos=new ObjectOutputStream(Client.socket.getOutputStream());
oos.writeObject(cmd);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Service类服务端主要实现监听客户端的连接

package cn.edu.xynu.socket;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;



/**
* @author scx
* 服务端
*/
public class Service {
public Service(){
try {
ServerSocket ss=new ServerSocket(8888);
Socket socket=null;
JOptionPane.showMessageDialog(null, "服务器已启动!请连接...");
//循环监听客户端的连接
while(true){
socket=ss.accept();
//为每个客户开启一个线程
ServiceThread serviceThread=new ServiceThread(socket);
Thread thread=new Thread(serviceThread);
thread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


}

服务器线程类,ServiceThread,多线程实现多用户的连接

package cn.edu.xynu.socket;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import cn.edu.xynu.entity.File;
import cn.edu.xynu.entity.User;
import cn.edu.xynu.service.FileService;
import cn.edu.xynu.service.UserService;
import cn.edu.xynu.util.CommandTranser;

/**
* @author scx
* 服务器线程
*/
public class ServiceThread implements Runnable {
private Socket socket;

public ServiceThread(Socket socket) {
this.socket = socket;
}

@Override
public void run() {
// TODO Auto-generated method stub
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
CommandTranser cmd=(CommandTranser) ois.readObject();
//处理客户端发送来的数据
cmd=execute(cmd);
oos.writeObject(cmd);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(ois!=null)
ois.close();
if(oos!=null){
oos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
//处理客户端发送来的数据
private CommandTranser execute(CommandTranser cmd) {
// TODO Auto-generated method stub
//客户端登录操作
if("login".equals(cmd.getCmd())){
UserService userService=new UserService();
User user=(User) cmd.getData();
cmd.setFlag(userService.checkUser(user));
if(cmd.isFlag()){
cmd.setResult("登录成功!!");
}else{
cmd.setResult("oh my god !!登录失败了。。");
}
}
//客户端注册用户操作
if("register".equals(cmd.getCmd())){
UserService userService=new UserService();
User user=(User) cmd.getData();
cmd.setFlag(userService.addUser(user));
if(cmd.isFlag()){
cmd.setResult("恭喜你。注册成功,请登录!");
}else{
cmd.setResult("oh my god !!注册失败了..");
}
}
//客户端上传文件操作
if("uploadFile".equals(cmd.getCmd())){
FileService fileService=new FileService();
File file=(File) cmd.getData();
cmd.setFlag(fileService.uploadFile(file));
if(cmd.isFlag()){
cmd.setResult("恭喜你,上传成功!");
}else{
cmd.setResult("很遗憾,上传失败!");
}
}
return cmd;
}

}

cn.edu.xynu.ui 都是各种界面设计

 

客户端登录界面loginUI类

 

package cn.edu.xynu.ui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import cn.edu.xynu.entity.User;
import cn.edu.xynu.socket.Client;
import cn.edu.xynu.util.CommandTranser;

/**
* @author scx
* 客户端登录界面
*/
public class LoginUI extends JFrame implements ActionListener {
private static final long serialVersionUID = -2686222552198867018L;
private Box box1, box2, box3, baseBox;
private JLabel username, password;
private JTextField username_txt;
private JPasswordField password_txt;
private JButton login_btn, register_btn;
public LoginUI() {
setLayout(new FlowLayout());
init();
setTitle("客户端");
setSize(200, 150);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
}

private void init() {
username = new JLabel("账户");
password = new JLabel("密码");
username_txt = new JTextField(10);
password_txt = new JPasswordField(10);
login_btn = new JButton("登录");
register_btn = new JButton("注册");
box1 = Box.createHorizontalBox();
box2 = Box.createHorizontalBox();
box3 = Box.createHorizontalBox();
box1.add(username);
box1.add(Box.createHorizontalStrut(8));
box1.add(username_txt);
box2.add(password);
box2.add(Box.createHorizontalStrut(8));
box2.add(password_txt);
box3.add(login_btn);
box3.add(Box.createHorizontalStrut(8));
box3.add(register_btn);
baseBox = Box.createVerticalBox();
baseBox.add(box1);
baseBox.add(Box.createVerticalStrut(5));
baseBox.add(box2);
baseBox.add(Box.createVerticalStrut(5));
baseBox.add(box3);
baseBox.add(Box.createVerticalStrut(5));
add(baseBox);
login_btn.addActionListener(this);
register_btn.addActionListener(this);
}

@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
//如果点击了登录按钮 判断账户在服务器是否存在
if(e.getSource()==login_btn){
User user=new User();
user.setUsername(username_txt.getText().trim());
user.setPassword(new String(password_txt.getPassword()).trim());
CommandTranser cmd =new CommandTranser();
cmd.setData(user);
cmd.setCmd("login");
try {
Client.socket=new Socket(Client.address, Client.port);
//向服务器发送数据
Client.sendData(cmd);
//获得服务器发送的数据
cmd =Client.getData();
JOptionPane.showMessageDialog(null, cmd.getResult());
//如果登录成功 关闭此窗口 开启上传窗口
if(cmd.isFlag()){
this.dispose();
new UploadUI(user.getUsername());
}
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null, "服务端未开启!");
} catch (IOException e1) {
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null, "服务端未开启!");
}
}
//如果点击了注册按钮 打开注册界面
if(e.getSource()==register_btn){
new RegisterUI();
}
}


}

客户端注册界面RegisterUI类

package cn.edu.xynu.ui;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import cn.edu.xynu.entity.User;
import cn.edu.xynu.socket.Client;
import cn.edu.xynu.util.CommandTranser;

/**
* @author scx
* 客户端注册界面
*/
public class RegisterUI extends JFrame implements ActionListener{
private static final long serialVersionUID = -717590965372186957L;
private Box box1, box2, baseBox;
private JLabel username, password,password2;
private JTextField username_txt;
private JPasswordField password_txt,password_txt2;
private JButton cancel_btn, register_btn;
public RegisterUI(){
setLayout(new FlowLayout());
init();
setTitle("注册");
setSize(250, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
setVisible(true);
setResizable(false);
}
private void init() {
// TODO Auto-generated method stub
username = new JLabel("账户");
password = new JLabel("密码");
password2=new JLabel("再次输入密码");
username_txt = new JTextField(10);
password_txt = new JPasswordField(10);
password_txt2=new JPasswordField(10);
cancel_btn = new JButton("取消");
register_btn = new JButton("注册");
box1=Box.createVerticalBox();
box2=Box.createVerticalBox();
box1.add(username);
box1.add(Box.createVerticalStrut(10));
box1.add(password);
box1.add(Box.createVerticalStrut(10));
box1.add(password2);
box1.add(Box.createVerticalStrut(10));

box2.add(username_txt);
box2.add(Box.createVerticalStrut(10));
box2.add(password_txt);
box2.add(Box.createVerticalStrut(10));
box2.add(password_txt2);
box2.add(Box.createVerticalStrut(10));
baseBox=Box.createHorizontalBox();
baseBox.add(box1);
baseBox.add(Box.createHorizontalStrut(5));
baseBox.add(box2);
add(baseBox);
add(register_btn);
add(cancel_btn);
cancel_btn.addActionListener(this);
register_btn.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource()==register_btn){
String username=username_txt.getText().trim();
String password1=new String(password_txt.getPassword()).trim();
String password2=new String(password_txt2.getPassword()).trim();
if(username==null||"".equals(username)){
JOptionPane.showMessageDialog(null, "请输入用户名!!");
return ;
}
if(password1==null||"".equals(password1)){
JOptionPane.showMessageDialog(null, "请输入密码!!");
return ;
}
if(!(password1.equals(password2))){
JOptionPane.showMessageDialog(null, "两次输入的密码不一致!!");
return ;
}
//向服务器发送注册信息
User user=new User(username, password1);
CommandTranser cmd=new CommandTranser();
cmd.setCmd("register");
cmd.setData(user);
try {
Client.socket=new Socket(Client.address, Client.port);
//向服务器发送数据
Client.sendData(cmd);
//获得服务器发送的数据
cmd =Client.getData();
JOptionPane.showMessageDialog(null, cmd.getResult());
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//初始化文本框
if(e.getSource()==cancel_btn){
username_txt.setText(null);
password_txt.setText(null);
password_txt2.setText(null);
}
}
}

开启客户端界面

package cn.edu.xynu.ui;

/**
* @author scx
* 开启客户端
*/
public class StartClient {
public static void main(String[] args) {
new LoginUI();
}
}

开启服务端界面,需要注意一点、

在线程中开启服务器 避免使用main线程 服务器一直开启
 main线程一直阻塞 无法对其它事物进行处理

package cn.edu.xynu.ui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

import cn.edu.xynu.socket.Service;
/**
* 开启服务端界面
*/
public class StartServer extends JFrame implements ActionListener{
private static final long serialVersionUID = 3254784569816648178L;
private JButton startServer_btn;
private JButton endServer_btn;
private Service startService;
public StartServer(){
setLayout(new FlowLayout());
startServer_btn=new JButton("开启服务");
endServer_btn=new JButton("关闭服务");
add(startServer_btn);
add(endServer_btn);
setTitle("服务端");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
startServer_btn.addActionListener(this);
endServer_btn.addActionListener(this);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StartServer();
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource()==startServer_btn){
if(startService==null){
/*
* 在线程中开启服务器 避免使用main线程 服务器一直开启
* main线程一直阻塞 无法对其它事物进行处理
*/
new startServerThread().start();
}
}
//退出服务器
if(e.getSource()==endServer_btn){
startService=null;
System.exit(0);
}
}
private class startServerThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
startService=new Service();
}
}
}

 

文件上传界面,主要控件有

 

一个选择文件按钮  一个确认上传按钮,一个显示文件路径的文本框

 

package cn.edu.xynu.ui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

import cn.edu.xynu.entity.File;
import cn.edu.xynu.socket.Client;
import cn.edu.xynu.util.CommandTranser;

/**
* @author scx
* 上传文件界面
*/
public class UploadUI extends JFrame implements ActionListener {
private static final long serialVersionUID = -8830003248247613172L;
private JFileChooser fileChooser;//文件选择对话框
private JButton upload_btn, choose_btn;//上传按钮 和选择按钮
private JTextField path_txt;//文件的绝对路径
private String username;//成功登录的用户名

public UploadUI(String username) {
this.username = username;
init();
setTitle("上传文件");
setSize(250, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
}

private void init() {
// TODO Auto-generated method stub
setLayout(new FlowLayout());
choose_btn = new JButton("选择");
upload_btn = new JButton("上传");
fileChooser = new JFileChooser();
path_txt = new JTextField(20);
add(path_txt);
add(choose_btn);
add(upload_btn);
choose_btn.addActionListener(this);
upload_btn.addActionListener(this);
}

@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
// 如果点击了选择文件
if (e.getSource() == choose_btn) {
//打开选择文件对话框
int state = fileChooser.showSaveDialog(null);
if (state == 0) {
String pathChoose = fileChooser.getSelectedFile().getPath();
path_txt.setText(pathChoose);
}
}
// 如果点击了上传按钮
if (e.getSource() == upload_btn) {
if(path_txt.getText().trim()==null||"".equals(path_txt.getText().trim())){
JOptionPane.showMessageDialog(null, "请先选择文件再上传!!");
return ;
}
uploadFile();
}
}
//上传文件
private void uploadFile() {
// TODO Auto-generated method stub
File file = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
String path = path_txt.getText().trim();
String fname = path.substring(path.lastIndexOf("\\") + 1);
try {
fis = new FileInputStream(path);
// fis.available返回文件的总大小
byte[] fcontent = new byte[fis.available()];
bis = new BufferedInputStream(fis);
//读取文件内容
bis.read(fcontent);
//实例化file对象
file = new File(fname, username, fcontent);

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bis != null)
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//向服务器发送文件
CommandTranser cmd = new CommandTranser();
cmd.setData(file);
cmd.setCmd("uploadFile");
try {
Client.socket = new Socket(Client.address,
Client.port);
//向服务器发送数据
Client.sendData(cmd);
//获得服务器反馈信息
cmd = Client.getData();
JOptionPane.showMessageDialog(null, cmd.getResult());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

cn.edu.xynu.util包里面就是工具类 

CommandTranser类 主要负责客户端向服务端发送数据以及服务器向客户端返回的数据

 

package cn.edu.xynu.util;

import java.io.Serializable;

/**
* @author scx
* 用户指令类
*/
public class CommandTranser implements Serializable{
private static final long serialVersionUID = 1L;
private String cmd;//操作指令
private Object data;//发送的数据
private boolean flag;//操作是否成功
private String result;//返回的结果
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}

}

数据库工具类

package cn.edu.xynu.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
* @author scx
* 数据库
*/
public class DBHelper {
private static final String driver="com.mysql.jdbc.Driver";
private static final String url="jdbc:mysql://localhost:3306/susu?useUnicode=true&charcterEncoding=UTF-8";
private static final String username="root";
private static final String password="";
private static Connection con=null;
//静态块代码负责加载驱动
static
{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection(){

if(con==null){
try {
con=DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return con;
}
}