java Socket(TCP)编程小项目

package 服务器端相关操作;

import java.io.Serializable;

/*
* 创建存储需要传输信息的对象,方便客户端向服务器端传送数据
*/
public class ClientToServerInfo implements Serializable{
String sign;
String name;
String password_OR_path;
//重写构造函数
public ClientToServerInfo(String sign,String name,String password_OR_path){
this.sign=sign;
this.name=name;
this.password_OR_path=password_OR_path;
} public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getName() {
return name;
}
public void setName(String Name) {
this.name = name;
}
public String getPassword_OR_path() {
return password_OR_path;
}
public void setPassword_OR_path(String password_OR_path) {
this.password_OR_path = password_OR_path;
}
@Override
public String toString() {
return "客户端说: [sign=" + sign + ", name=" + name + ", password_OR_path=" +password_OR_path + "]";
} } import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; /*
* 服务器端主程序操作
*/
public class Server { public static void main(String[] args) {
try {
//1.创建服务器端的ServerSocket,指定伴随的端口号
ServerSocket serversocket=new ServerSocket(8880);
System.out.println("****服务器端即将启动,等待客户端*****");// 提示服务器开启
Socket socket=null;
while(true){
//2.调用accept()方法开始监听,等待客户端连接 socket=serversocket.accept();
//调用线程
ServerThread st=new ServerThread(socket);
st.start();
} } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
} import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException; import Server_To_Client_Response.Add_File_Response;
import Server_To_Client_Response.Add_User_Response;
import Server_To_Client_Response.Select_User_Response; public class ServerThread extends Thread {
//创建与本线程相关的socket
Socket socket=null;
ObjectInputStream ois=null;
//重写构造函数
public ServerThread(Socket socket){
this.socket=socket;
}
//线程操作 获取输出流,响应客户端的请求
public void run(){ try {
//3.获取输入流,并读取客户端信息
ois=new ObjectInputStream(socket.getInputStream());
/*
* 读取接收到的对象信息
*/
while( ois.available()!=-1){
ClientToServerInfo ctsi =(ClientToServerInfo)ois.readObject();
System.out.println(ctsi.toString());//打印客户端传到服务器的数据(对象)
/*
* 需要客户端传入的对象数据进行分析,根据传入的sign标志值进行相应的操作
* sign="1"完成注册会员操作,链接数据库,向数据库中user表添加记录
* sign="2"完成会员登录操作,连接数据库,在数据库中user表查询记录
* sign="3"完成文件上传操作,连接数据库,向数据库中file表添加记录
*/
//System.out.println(ctsi.sign);
if(ctsi.sign.equals("1")){
//调用 Add_User_Response类的构造方法对客户端传入的信息进行详细的响应
Add_User_Response aur=new Add_User_Response(socket, ctsi.name,ctsi.password_OR_path);
//System.out.println("运行完Add_User_Response类");
break;
}
if(ctsi.sign.equals("2")){
//调用 Select_User_Response类的构造方法对客户端传入的信息进行详细的响应
Select_User_Response sur=new Select_User_Response(socket, ctsi.name,ctsi.password_OR_path);
//System.out.println("运行完 Select_User_Response类");
break;
}
if(ctsi.sign.equals("3")){
//调用 Add_File_Response类的构造方法对客户端传入的信息进行详细的响应
Add_File_Response afr=new Add_File_Response(socket, ctsi.name,ctsi.password_OR_path);
// System.out.println("运行完 Add_File_Response类");
break;
}
} //5.关闭资源
ois.close(); } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
 package 客户端相关操作;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner; import org.eclipse.persistence.oxm.record.OutputStreamRecord; import 服务器端相关操作.ClientToServerInfo; public class Client { public static void main(String[] args) throws UnknownHostException, IOException {
String []data=new String[3];
int sum=0;//用来记录客户端第几次传值到服务器端
/*
* 客户端界面的提示语句
*/
ClientTips ctps=new ClientTips();
Scanner sc=new Scanner(System.in);
int n; /*
* 客户端实现与服务器端交互
*/ try {
while(true){//使得客户端始终处于程序运行当中
//1.创建客户端socket,指定服务器和端口号
Socket socket=new Socket("localhost", 8880);
OutputStream os=null;
InputStream is=null;
InputStreamReader isr=null;
BufferedReader br=null;
ClientToServerInfo ctsi=null;
ObjectOutputStream oos=null;
while(true){//通过循环让客户端完成注册、登录 和上传信息的客户界面操作
n=sc.nextInt();
/*
* data用于接收tipchoose返回的字符串数组
* 如果传入的值为1时返回的为三个非空字符串,分别为“1”和用户名和密码
* 如果传入的值为2是返回的为两个非空字符串,分别是“2”和用户名和密码
* 如果传入的值为3是返回的两个字符串,分别是“3”和data[0]=null,data[1]=文件路径
*/
data=ctps.tipChoose(n);
if(data[0]!=null&&data[1]!=null){
//如果界面输入值合理,则跳出一层循环
break;
}
} //2.获取输出流,向服务器端发送信息
os=socket.getOutputStream();//字节输出流 /*
*这里要判断是不是第一次写文件,若是则写入头部,否则不写入。
*/
//if(sum==0){
oos=new ObjectOutputStream(os);
//}
/*else{
System.out.println(sum);
oos=new MyObjectOutputStream(os);
}*/ //将需要传送的信息封装成对象
ctsi=new ClientToServerInfo(data[0],data[1],data[2]); oos.writeObject(ctsi);
oos.writeObject(null);//objectoutputstream写入结束的标志
oos.flush();
sum++;
//socket.shutdownOutput();//关闭输出流 //3.读取服务器端发送的信息
is=socket.getInputStream();
isr=new InputStreamReader(is);
br=new BufferedReader(isr);
String info=null;
if((info=br.readLine())!=null){
System.out.println("我是客户端,服务器说:"+info);
}
//用来区分不同次的客户端发送和服务器响应的命令
System.out.println("**************************");
//关闭输入输出流(关闭资源)
br.close();
isr.close();
is.close();
oos.close();
os.close();
socket.close(); }
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} import java.util.Scanner; public class ClientTips {
static boolean flag=false;
static String a;
public ClientTips(){
//打印客户端界面
System.out.println("*********************************");
System.out.println("注册信息:1");
System.out.println("登陆账号:2");
System.out.println("上传文件(只有在登陆之后才能传文件!):3");
System.out.println("*********************************");
}
public String[] tipChoose(int n){
String[] userinfo=new String[3];
String b,c,e;
Scanner sc=new Scanner(System.in); /*
* 注册时的提示操作
*/
if(n==1){
System.out.print("请输入要注册的账号名:");
a=sc.nextLine();
System.out.print("请输入密码:");
b=sc.nextLine();
System.out.print("请确认密码:");
c=sc.nextLine();
if(!c.equals(b)){//这里不能用c!=b判断,c!=b不仅对比了字符串,还对比了存储地址
System.out.println("密码不一致!注册失败,需要重新注册请输入:1");
//如果注册失败,userinfo返回的为空数组
userinfo[0]=null;
userinfo[1]=null;
userinfo[2]=null;
}
else{
userinfo[0]="1";
userinfo[1]=a;
userinfo[2]=b;
}
}
/*
* 登陆时提示信息操作
*/
if(n==2){
System.out.print("请输入要登陆的账号名:");
a=sc.nextLine();
System.out.print("请输入密码:");
b=sc.nextLine();
userinfo[0]="2";
userinfo[1]=a;
userinfo[2]=b;
flag=true; } /*
* 传送文件相关文件
*/
if(n==3){
if(flag!=true){
System.out.println("请先登录账号!请输入2");
//如果没有登陆操作,输入3时先返回空数组
userinfo[0]=null;
userinfo[1]=null;
userinfo[2]=null;
}
else{
System.out.println("请输入文件的路径:");
e=sc.nextLine();
userinfo[0]="3";
userinfo[1]=a;
userinfo[2]=e;
}
}
return userinfo;
}
} import java.io.Serializable; /*
* 创建存储需要传输信息的对象,方便客户端向服务器端传送数据
*/
public class ClientToServerInfo implements Serializable{
String sign;
String name;
String password_OR_path;
//重写构造函数
public ClientToServerInfo(String sign,String name,String password_OR_path){
this.sign=sign;
this.name=name;
this.password_OR_path=password_OR_path;
} public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getName() {
return name;
}
public void setName(String Name) {
this.name = name;
}
public String getPassword_OR_path() {
return password_OR_path;
}
public void setPassword_OR_path(String password_OR_path) {
this.password_OR_path = password_OR_path;
}
@Override
public String toString() {
return "客户端说: [sign=" + sign + ", name=" + name + ", password_OR_path=" +password_OR_path + "]";
} } import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
/*
* 在一个文件都有一个文件的头部和文件体。由于对多次使用FileOutputStream(文件名,true)
* 构建的ObjectOutputStream对象向同一个文件写数据,在每次些数据的时候他都会向这个文件末
* 尾先写入header在写入你要写的对象数据,在读取的时候遇到这个在文件体中的header就会报错。
* 导致读出时,出现streamcorrput异常。(解决办法:所以这里要判断是不是第一次写文件,若是
* 则写入头部,否则不写入)
*/
public class MyObjectOutputStream extends ObjectOutputStream { protected MyObjectOutputStream() throws IOException, SecurityException {
super();
} public MyObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override protected void writeStreamHeader() throws IOException {
return;
}
}
 package Database;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException; public class DBUtil { private static final String URL="jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&characterEncoding=utf-8";
private static final String USER="root";
private static final String PASSWORD="tiger"; private static Connection conn=null; static {
try {
//1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库的连接
conn=DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
//将获得的数据库与java的链接返回(返回的类型为Connection)
public static Connection getConnection(){
return conn;
} } /*
* 服务器端链接数据库,并向数据库表user添加数据
* 添加成功返回true,否则返回false
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; public class Database_Add_User {
boolean flag=false;
//
public boolean Database_Add_User_run(String name,String password_OR_path) throws SQLException{
//获取mysql链接
System.out.println("开始运行Database_Add_User类");
Connection conn=DBUtil.getConnection();
String sql=""+"insert into user"+"(user_name,user_password)"
+"values("+"?,?)";
//加载sql语句到执行程序中(并不进行执行)
PreparedStatement ptmt=conn.prepareStatement(sql);
ptmt.setString(1, name);
ptmt.setString(2, password_OR_path);
flag=ptmt.execute();
return flag;
}
} /*
* 用于用户登录时,将账号和密码传递到数据库,
* 若登录名不存在file表中(即未注册)返回2
* 若登录名存在file表中,密码输入正确返回1
* 若登录名存在file表中,密码输入错误返回3
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class Database_Select_User { public int Database_Select_User_run(String name,String password_OR_path) throws SQLException{
//获取mysql链接
Connection conn=DBUtil.getConnection();
String sql1=""+"select * from user where user_name like ?";
PreparedStatement ptmt=conn.prepareStatement(sql1.toString());
ptmt.setString(1, "%"+name+"%");
ResultSet rs=ptmt.executeQuery();
while(rs.next()){
//判断密码是否正确,正确返回1
if(rs.getString("user_password").equals(password_OR_path)){
return 1;
}
//判断密码错误返回2
else
return 3;
}
//用户名不存在返回2
return 2; } } /*
* 服务器端链接数据库,并向数据库表file添加数据
* 添加成功返回false,否则返回true
*/ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; public class Database_Add_File {
boolean flag=false;
//
public boolean Database_Add_File_run(String name,String password_OR_path) throws SQLException, FileNotFoundException{
//获取mysql链接
File files = new File(password_OR_path);
Connection conn=DBUtil.getConnection();
String sql=""+"insert into file"+"(user_name,path)"
+"values("+"?,?)";
//加载sql语句到执行程序中(并不进行执行)
PreparedStatement ptmt=conn.prepareStatement(sql);
ptmt.setString(1, name);
//ptmt.setString(2, password_OR_path);
FileInputStream fis = new FileInputStream(files);
ptmt.setBinaryStream(2, (InputStream) fis, (int) (files.length()));
flag=ptmt.execute();
return flag;
}
}
 package Server_To_Client_Response;
/*
* 判断客户端传入到服务器端的注册会员数据,提交到数据库中,
* 是否在数据库中添加成功,并完成对客户端的响应,成功返回注册成功,
* 反之提示其重新注册
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException; import Database.Database_Add_User; public class Add_User_Response {
Socket socket=null;
boolean flag;
public Add_User_Response(Socket socket,String name,
String password_OR_path ) throws SQLException{ try {
System.out.println("运行Add_User_Response类");
//将已创建的socket对象加载进来 this.socket=socket;
OutputStream os=socket.getOutputStream();
PrintWriter pw=new PrintWriter(os);
/*
* 创建和数据库的链接,完成向user表格中添加记录操作
* 添加成功返回false,否则返回true
*/
Database_Add_User dau=new Database_Add_User();
flag=dau.Database_Add_User_run(name, password_OR_path);
//System.out.println("运行完Database_Add_User类");
/*
* 对插入数据后的返回值进行分析,并对客户端进行响应
*/
if(!flag){
//获取输出流,响应客户端的请求
pw.write("您已经成功注册!");
pw.flush(); }
else{
pw.write("注册失败!");
pw.flush(); }
//关闭输入输出流(关闭资源)
pw.close();
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally { try { socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
} /*
* 判断客户端传入到服务器端的上传文件数据,提交到数据库中,
* 是否在数据库中添加成功,并完成对客户端的响应,成功返回上传成功,
* 反之提示其重新上传
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException; import Database.Database_Add_File; public class Add_File_Response {
OutputStream os=null;
PrintWriter pw=null;
Socket socket=null;
boolean flag;
public Add_File_Response(Socket socket,String name,
String password_OR_path ) throws SQLException, IOException{
//将已创建的socket对象加载进来
this.socket=socket;
os=socket.getOutputStream();
pw=new PrintWriter(os);
/*
* 创建和数据库的链接,完成向file表格中添加记录操作
* 添加成功返回false,否则返回true
*/ Database_Add_File dau=new Database_Add_File();
flag=dau.Database_Add_File_run(name, password_OR_path); /*
* 对插入数据后的返回值进行分析,并对客户端进行响应
*/
if(!flag){
//获取输出流,响应客户端的请求
pw.write("文件上传成功!");
pw.flush();
}
else{
pw.write("文件上传失败!请重新上传!");
pw.flush();
}
//关闭输入输出流(关闭资源)
pw.close();
os.close();
}
} /*
* 判断客户端传入到服务器端的会员数据,提交到数据库中,
* 在数据库中查找,是否注册,密码是否正确,若账号名和密码都正确,登陆成功
* 并完成对客户端的响应。
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException; import Database.Database_Select_User; public class Select_User_Response {
//输出流的初始化,为服务器对客户端的响应做准备
OutputStream os=null;
PrintWriter pw=null;
Socket socket=null;
int flag;
public Select_User_Response(Socket socket,String name,
String password_OR_path) throws IOException, SQLException{
this.socket=socket;
os=socket.getOutputStream();
pw=new PrintWriter(os);
/*
* 创建和数据库的链接,完成对user表格的查询操作(完成登陆)
* 若登录名不存在file表中(即未注册)返回2
* 若登录名存在file表中,密码输入正确返回1
* 若登录名存在file表中,密码输入错误返回3
*/
Database_Select_User dsu=new Database_Select_User();
flag=dsu.Database_Select_User_run(name,password_OR_path); /*
* 对查找返回的数据进行分析,并对客户端进行响应
*/
if(flag==1){
pw.write("欢迎您,你已经完成登陆!请输入3");
pw.flush();
}
else if(flag==2){
pw.write("您还没进行注册,请先注册!");
pw.flush();
}
else{
pw.write("密码错误!请重新登陆!请输入2");
pw.flush();
}
//关闭输出输入流(关闭资源)
pw.close();
os.close();
}
}
上一篇:【深度学习之美】卷地风来忽吹散,积得飘零美如画(入门系列之十)


下一篇:Android日语输入法Simeji使用示例