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();
            }
        
        }

     }
  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM