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(); } } }
1 package 客戶端相關操作; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.ObjectOutputStream; 8 import java.io.OutputStream; 9 import java.io.PrintWriter; 10 import java.net.Socket; 11 import java.net.UnknownHostException; 12 import java.util.Scanner; 13 14 import org.eclipse.persistence.oxm.record.OutputStreamRecord; 15 16 import 服務器端相關操作.ClientToServerInfo; 17 18 public class Client { 19 20 public static void main(String[] args) throws UnknownHostException, IOException { 21 String []data=new String[3]; 22 int sum=0;//用來記錄客戶端第幾次傳值到服務器端 23 /* 24 * 客戶端界面的提示語句 25 */ 26 ClientTips ctps=new ClientTips(); 27 Scanner sc=new Scanner(System.in); 28 int n; 29 30 /* 31 * 客戶端實現與服務器端交互 32 */ 33 34 try { 35 while(true){//使得客戶端始終處於程序運行當中 36 //1.創建客戶端socket,指定服務器和端口號 37 Socket socket=new Socket("localhost", 8880); 38 OutputStream os=null; 39 InputStream is=null; 40 InputStreamReader isr=null; 41 BufferedReader br=null; 42 ClientToServerInfo ctsi=null; 43 ObjectOutputStream oos=null; 44 while(true){//通過循環讓客戶端完成注冊、登錄 和上傳信息的客戶界面操作 45 n=sc.nextInt(); 46 /* 47 * data用於接收tipchoose返回的字符串數組 48 * 如果傳入的值為1時返回的為三個非空字符串,分別為“1”和用戶名和密碼 49 * 如果傳入的值為2是返回的為兩個非空字符串,分別是“2”和用戶名和密碼 50 * 如果傳入的值為3是返回的兩個字符串,分別是“3”和data[0]=null,data[1]=文件路徑 51 */ 52 data=ctps.tipChoose(n); 53 if(data[0]!=null&&data[1]!=null){ 54 //如果界面輸入值合理,則跳出一層循環 55 break; 56 } 57 } 58 59 60 //2.獲取輸出流,向服務器端發送信息 61 os=socket.getOutputStream();//字節輸出流 62 63 /* 64 *這里要判斷是不是第一次寫文件,若是則寫入頭部,否則不寫入。 65 */ 66 //if(sum==0){ 67 oos=new ObjectOutputStream(os); 68 //} 69 /*else{ 70 System.out.println(sum); 71 oos=new MyObjectOutputStream(os); 72 }*/ 73 74 75 //將需要傳送的信息封裝成對象 76 ctsi=new ClientToServerInfo(data[0],data[1],data[2]); 77 78 oos.writeObject(ctsi); 79 oos.writeObject(null);//objectoutputstream寫入結束的標志 80 oos.flush(); 81 sum++; 82 //socket.shutdownOutput();//關閉輸出流 83 84 //3.讀取服務器端發送的信息 85 is=socket.getInputStream(); 86 isr=new InputStreamReader(is); 87 br=new BufferedReader(isr); 88 String info=null; 89 if((info=br.readLine())!=null){ 90 System.out.println("我是客戶端,服務器說:"+info); 91 } 92 //用來區分不同次的客戶端發送和服務器響應的命令 93 System.out.println("**************************"); 94 //關閉輸入輸出流(關閉資源) 95 br.close(); 96 isr.close(); 97 is.close(); 98 oos.close(); 99 os.close(); 100 socket.close(); 101 102 } 103 } catch (IOException e) { 104 // TODO Auto-generated catch block 105 e.printStackTrace(); 106 } 107 } 108 } 109 110 111 import java.util.Scanner; 112 113 public class ClientTips { 114 static boolean flag=false; 115 static String a; 116 public ClientTips(){ 117 //打印客戶端界面 118 System.out.println("*********************************"); 119 System.out.println("注冊信息:1"); 120 System.out.println("登陸賬號:2"); 121 System.out.println("上傳文件(只有在登陸之后才能傳文件!):3"); 122 System.out.println("*********************************"); 123 } 124 public String[] tipChoose(int n){ 125 String[] userinfo=new String[3]; 126 String b,c,e; 127 Scanner sc=new Scanner(System.in); 128 129 /* 130 * 注冊時的提示操作 131 */ 132 if(n==1){ 133 System.out.print("請輸入要注冊的賬號名:"); 134 a=sc.nextLine(); 135 System.out.print("請輸入密碼:"); 136 b=sc.nextLine(); 137 System.out.print("請確認密碼:"); 138 c=sc.nextLine(); 139 if(!c.equals(b)){//這里不能用c!=b判斷,c!=b不僅對比了字符串,還對比了存儲地址 140 System.out.println("密碼不一致!注冊失敗,需要重新注冊請輸入:1"); 141 //如果注冊失敗,userinfo返回的為空數組 142 userinfo[0]=null; 143 userinfo[1]=null; 144 userinfo[2]=null; 145 } 146 else{ 147 userinfo[0]="1"; 148 userinfo[1]=a; 149 userinfo[2]=b; 150 } 151 } 152 /* 153 * 登陸時提示信息操作 154 */ 155 if(n==2){ 156 System.out.print("請輸入要登陸的賬號名:"); 157 a=sc.nextLine(); 158 System.out.print("請輸入密碼:"); 159 b=sc.nextLine(); 160 userinfo[0]="2"; 161 userinfo[1]=a; 162 userinfo[2]=b; 163 flag=true; 164 165 } 166 167 /* 168 * 傳送文件相關文件 169 */ 170 if(n==3){ 171 if(flag!=true){ 172 System.out.println("請先登錄賬號!請輸入2"); 173 //如果沒有登陸操作,輸入3時先返回空數組 174 userinfo[0]=null; 175 userinfo[1]=null; 176 userinfo[2]=null; 177 } 178 else{ 179 System.out.println("請輸入文件的路徑:"); 180 e=sc.nextLine(); 181 userinfo[0]="3"; 182 userinfo[1]=a; 183 userinfo[2]=e; 184 } 185 } 186 return userinfo; 187 } 188 } 189 190 191 import java.io.Serializable; 192 193 /* 194 * 創建存儲需要傳輸信息的對象,方便客戶端向服務器端傳送數據 195 */ 196 public class ClientToServerInfo implements Serializable{ 197 String sign; 198 String name; 199 String password_OR_path; 200 //重寫構造函數 201 public ClientToServerInfo(String sign,String name,String password_OR_path){ 202 this.sign=sign; 203 this.name=name; 204 this.password_OR_path=password_OR_path; 205 } 206 207 public String getSign() { 208 return sign; 209 } 210 public void setSign(String sign) { 211 this.sign = sign; 212 } 213 public String getName() { 214 return name; 215 } 216 public void setName(String Name) { 217 this.name = name; 218 } 219 public String getPassword_OR_path() { 220 return password_OR_path; 221 } 222 public void setPassword_OR_path(String password_OR_path) { 223 this.password_OR_path = password_OR_path; 224 } 225 @Override 226 public String toString() { 227 return "客戶端說: [sign=" + sign + ", name=" + name + ", password_OR_path=" +password_OR_path + "]"; 228 } 229 230 } 231 232 233 import java.io.IOException; 234 import java.io.ObjectOutputStream; 235 import java.io.OutputStream; 236 /* 237 * 在一個文件都有一個文件的頭部和文件體。由於對多次使用FileOutputStream(文件名,true) 238 * 構建的ObjectOutputStream對象向同一個文件寫數據,在每次些數據的時候他都會向這個文件末 239 * 尾先寫入header在寫入你要寫的對象數據,在讀取的時候遇到這個在文件體中的header就會報錯。 240 * 導致讀出時,出現streamcorrput異常。(解決辦法:所以這里要判斷是不是第一次寫文件,若是 241 * 則寫入頭部,否則不寫入) 242 */ 243 public class MyObjectOutputStream extends ObjectOutputStream { 244 245 protected MyObjectOutputStream() throws IOException, SecurityException { 246 super(); 247 } 248 249 250 public MyObjectOutputStream(OutputStream out) throws IOException { 251 super(out); 252 } 253 @Override 254 255 protected void writeStreamHeader() throws IOException { 256 return; 257 } 258 }
1 package Database; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 7 public class DBUtil { 8 9 private static final String URL="jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&characterEncoding=utf-8"; 10 private static final String USER="root"; 11 private static final String PASSWORD="tiger"; 12 13 private static Connection conn=null; 14 15 static { 16 try { 17 //1.加載驅動程序 18 Class.forName("com.mysql.jdbc.Driver"); 19 //2.獲得數據庫的連接 20 conn=DriverManager.getConnection(URL, USER, PASSWORD); 21 } catch (ClassNotFoundException e) { 22 e.printStackTrace(); 23 } catch (SQLException e) { 24 e.printStackTrace(); 25 } 26 } 27 //將獲得的數據庫與java的鏈接返回(返回的類型為Connection) 28 public static Connection getConnection(){ 29 return conn; 30 } 31 32 } 33 34 /* 35 * 服務器端鏈接數據庫,並向數據庫表user添加數據 36 * 添加成功返回true,否則返回false 37 */ 38 import java.sql.Connection; 39 import java.sql.PreparedStatement; 40 import java.sql.SQLException; 41 42 public class Database_Add_User { 43 boolean flag=false; 44 // 45 public boolean Database_Add_User_run(String name,String password_OR_path) throws SQLException{ 46 //獲取mysql鏈接 47 System.out.println("開始運行Database_Add_User類"); 48 Connection conn=DBUtil.getConnection(); 49 String sql=""+"insert into user"+"(user_name,user_password)" 50 +"values("+"?,?)"; 51 //加載sql語句到執行程序中(並不進行執行) 52 PreparedStatement ptmt=conn.prepareStatement(sql); 53 ptmt.setString(1, name); 54 ptmt.setString(2, password_OR_path); 55 flag=ptmt.execute(); 56 return flag; 57 } 58 } 59 60 /* 61 * 用於用戶登錄時,將賬號和密碼傳遞到數據庫, 62 * 若登錄名不存在file表中(即未注冊)返回2 63 * 若登錄名存在file表中,密碼輸入正確返回1 64 * 若登錄名存在file表中,密碼輸入錯誤返回3 65 */ 66 import java.sql.Connection; 67 import java.sql.PreparedStatement; 68 import java.sql.ResultSet; 69 import java.sql.SQLException; 70 71 public class Database_Select_User { 72 73 74 public int Database_Select_User_run(String name,String password_OR_path) throws SQLException{ 75 //獲取mysql鏈接 76 Connection conn=DBUtil.getConnection(); 77 String sql1=""+"select * from user where user_name like ?"; 78 PreparedStatement ptmt=conn.prepareStatement(sql1.toString()); 79 ptmt.setString(1, "%"+name+"%"); 80 ResultSet rs=ptmt.executeQuery(); 81 while(rs.next()){ 82 //判斷密碼是否正確,正確返回1 83 if(rs.getString("user_password").equals(password_OR_path)){ 84 return 1; 85 } 86 //判斷密碼錯誤返回2 87 else 88 return 3; 89 } 90 //用戶名不存在返回2 91 return 2; 92 93 } 94 95 } 96 97 /* 98 * 服務器端鏈接數據庫,並向數據庫表file添加數據 99 * 添加成功返回false,否則返回true 100 */ 101 102 import java.io.File; 103 import java.io.FileInputStream; 104 import java.io.FileNotFoundException; 105 import java.io.InputStream; 106 import java.sql.Connection; 107 import java.sql.PreparedStatement; 108 import java.sql.SQLException; 109 110 public class Database_Add_File { 111 boolean flag=false; 112 // 113 public boolean Database_Add_File_run(String name,String password_OR_path) throws SQLException, FileNotFoundException{ 114 //獲取mysql鏈接 115 File files = new File(password_OR_path); 116 Connection conn=DBUtil.getConnection(); 117 String sql=""+"insert into file"+"(user_name,path)" 118 +"values("+"?,?)"; 119 //加載sql語句到執行程序中(並不進行執行) 120 PreparedStatement ptmt=conn.prepareStatement(sql); 121 ptmt.setString(1, name); 122 //ptmt.setString(2, password_OR_path); 123 FileInputStream fis = new FileInputStream(files); 124 ptmt.setBinaryStream(2, (InputStream) fis, (int) (files.length())); 125 flag=ptmt.execute(); 126 return flag; 127 } 128 }
1 package Server_To_Client_Response; 2 /* 3 * 判斷客戶端傳入到服務器端的注冊會員數據,提交到數據庫中, 4 * 是否在數據庫中添加成功,並完成對客戶端的響應,成功返回注冊成功, 5 * 反之提示其重新注冊 6 */ 7 import java.io.IOException; 8 import java.io.OutputStream; 9 import java.io.PrintWriter; 10 import java.net.Socket; 11 import java.sql.SQLException; 12 13 import Database.Database_Add_User; 14 15 public class Add_User_Response { 16 Socket socket=null; 17 boolean flag; 18 public Add_User_Response(Socket socket,String name, 19 String password_OR_path ) throws SQLException{ 20 21 try { 22 System.out.println("運行Add_User_Response類"); 23 //將已創建的socket對象加載進來 24 25 this.socket=socket; 26 OutputStream os=socket.getOutputStream(); 27 PrintWriter pw=new PrintWriter(os); 28 /* 29 * 創建和數據庫的鏈接,完成向user表格中添加記錄操作 30 * 添加成功返回false,否則返回true 31 */ 32 Database_Add_User dau=new Database_Add_User(); 33 flag=dau.Database_Add_User_run(name, password_OR_path); 34 //System.out.println("運行完Database_Add_User類"); 35 /* 36 * 對插入數據后的返回值進行分析,並對客戶端進行響應 37 */ 38 if(!flag){ 39 //獲取輸出流,響應客戶端的請求 40 pw.write("您已經成功注冊!"); 41 pw.flush(); 42 43 } 44 else{ 45 pw.write("注冊失敗!"); 46 pw.flush(); 47 48 } 49 //關閉輸入輸出流(關閉資源) 50 pw.close(); 51 os.close(); 52 } catch (IOException e) { 53 // TODO Auto-generated catch block 54 e.printStackTrace(); 55 }finally { 56 57 try { 58 59 socket.close(); 60 } catch (IOException e) { 61 // TODO Auto-generated catch block 62 e.printStackTrace(); 63 } 64 } 65 66 } 67 } 68 69 70 /* 71 * 判斷客戶端傳入到服務器端的上傳文件數據,提交到數據庫中, 72 * 是否在數據庫中添加成功,並完成對客戶端的響應,成功返回上傳成功, 73 * 反之提示其重新上傳 74 */ 75 import java.io.IOException; 76 import java.io.OutputStream; 77 import java.io.PrintWriter; 78 import java.net.Socket; 79 import java.sql.SQLException; 80 81 import Database.Database_Add_File; 82 83 public class Add_File_Response { 84 OutputStream os=null; 85 PrintWriter pw=null; 86 Socket socket=null; 87 boolean flag; 88 public Add_File_Response(Socket socket,String name, 89 String password_OR_path ) throws SQLException, IOException{ 90 //將已創建的socket對象加載進來 91 this.socket=socket; 92 os=socket.getOutputStream(); 93 pw=new PrintWriter(os); 94 /* 95 * 創建和數據庫的鏈接,完成向file表格中添加記錄操作 96 * 添加成功返回false,否則返回true 97 */ 98 99 Database_Add_File dau=new Database_Add_File(); 100 flag=dau.Database_Add_File_run(name, password_OR_path); 101 102 /* 103 * 對插入數據后的返回值進行分析,並對客戶端進行響應 104 */ 105 if(!flag){ 106 //獲取輸出流,響應客戶端的請求 107 pw.write("文件上傳成功!"); 108 pw.flush(); 109 } 110 else{ 111 pw.write("文件上傳失敗!請重新上傳!"); 112 pw.flush(); 113 } 114 //關閉輸入輸出流(關閉資源) 115 pw.close(); 116 os.close(); 117 } 118 } 119 120 121 /* 122 * 判斷客戶端傳入到服務器端的會員數據,提交到數據庫中, 123 * 在數據庫中查找,是否注冊,密碼是否正確,若賬號名和密碼都正確,登陸成功 124 * 並完成對客戶端的響應。 125 */ 126 import java.io.IOException; 127 import java.io.OutputStream; 128 import java.io.PrintWriter; 129 import java.net.Socket; 130 import java.sql.SQLException; 131 132 import Database.Database_Select_User; 133 134 public class Select_User_Response { 135 //輸出流的初始化,為服務器對客戶端的響應做准備 136 OutputStream os=null; 137 PrintWriter pw=null; 138 Socket socket=null; 139 int flag; 140 public Select_User_Response(Socket socket,String name, 141 String password_OR_path) throws IOException, SQLException{ 142 this.socket=socket; 143 os=socket.getOutputStream(); 144 pw=new PrintWriter(os); 145 /* 146 * 創建和數據庫的鏈接,完成對user表格的查詢操作(完成登陸) 147 * 若登錄名不存在file表中(即未注冊)返回2 148 * 若登錄名存在file表中,密碼輸入正確返回1 149 * 若登錄名存在file表中,密碼輸入錯誤返回3 150 */ 151 Database_Select_User dsu=new Database_Select_User(); 152 flag=dsu.Database_Select_User_run(name,password_OR_path); 153 154 /* 155 * 對查找返回的數據進行分析,並對客戶端進行響應 156 */ 157 if(flag==1){ 158 pw.write("歡迎您,你已經完成登陸!請輸入3"); 159 pw.flush(); 160 } 161 else if(flag==2){ 162 pw.write("您還沒進行注冊,請先注冊!"); 163 pw.flush(); 164 } 165 else{ 166 pw.write("密碼錯誤!請重新登陸!請輸入2"); 167 pw.flush(); 168 } 169 //關閉輸出輸入流(關閉資源) 170 pw.close(); 171 os.close(); 172 } 173 }