Java建立 多人聊天室

雅興cnsd發表於2020-11-07

先執行伺服器端再執行客戶端

//這是客戶端
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.*;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;

public class Client {
 private Scanner scanner=null;
 private Socket socket=null;
 private String s="";
 public Client() {
   try {
    System.out.println("客戶端啟動");
    socket=new Socket("localhost",8051);
    System.out.println("客戶端已啟動");
   } catch (UnknownHostException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  
 }
 public void start() {
  try {
   ServerClient serverclient=new ServerClient();
   Thread t=new Thread(serverclient);
   t.start();
   
   OutputStream os=socket.getOutputStream();
   OutputStreamWriter osw=new OutputStreamWriter(os,"utf-8");
   BufferedWriter bw=new BufferedWriter(osw);
   PrintWriter pw=new PrintWriter(bw,true);
   scanner=new Scanner(System.in);
   while(true) {
    s=scanner.nextLine();
    if(s.equals("over")) break;
    pw.println(s);
   }
  }catch(SocketException e) {
   System.out.println("無內容");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   //e.printStackTrace();
  }
 }
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  Client c=new Client();
  c.start();
 }
 /*
  * 定義一個內部類進行內部的訊息處理
  */
 class ServerClient implements Runnable{
  public void run() {
   try {
    InputStream is=socket.getInputStream();
    InputStreamReader isr=new InputStreamReader(is,"utf-8");
    BufferedReader br=new BufferedReader(isr);
    String s;
    while((s=br.readLine())!=null) {
     System.err.println(s);
    }
   }catch(SocketException e) {
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}
//這是伺服器端
public class Server1 {
 private ServerSocket server=null;
 private ClientServer clientserver=null;
 private String s="";
 public PrintWriter[] allout= {};
 public Server1() {
  try {
   System.out.println("伺服器開始啟動");
   server=new ServerSocket(8051);
   System.out.println("伺服器已啟動");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 /*
  * 定義一個start方法進行對資訊接收及傳送的處理
  */
 
 public void start() {
  while(true) {
   try {
    System.out.println("--------------------------------");
    System.err.println("伺服器準備接收");
    Socket socket=server.accept();
    System.err.println("伺服器開始接收");
    System.out.println("---------------------------------");
    clientserver=new ClientServer(socket);
    Thread t=new Thread(clientserver);
    t.start();
   } catch (SocketException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }catch(IOException e) {
    e.getStackTrace();
   }
  } 
 }
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  Server1 s=new Server1();
  s.start();
 }
class ClientServer implements Runnable{
  private Socket socket=null;
  private String hostname="";
  private String words=null;
  public ClientServer(Socket socket) {
   this.socket=socket;
   this.hostname=socket.getInetAddress().getHostName();
  }
  @Override
  public void run() {
   InputStream is;
   PrintWriter pw=null ;
   try {
    /*
     * 獲得客戶端傳送過來的輸入流
     */
    is = socket.getInputStream();
    InputStreamReader isr=new InputStreamReader(is,"utf-8");
    BufferedReader br=new BufferedReader(isr);
    /*
     * 獲得伺服器要傳送到客戶端的輸出流
     */
    OutputStream os=socket.getOutputStream();
    OutputStreamWriter osw=new OutputStreamWriter(os,"utf-8");
    BufferedWriter bw=new BufferedWriter(osw);
    pw=new PrintWriter(bw,true);
    /*
     * 這個同步程式碼塊時有新的執行緒時執行一次的
     * 目的時將pw放入allout這個輸出流陣列中
     */
    synchronized(allout) {
     //陣列擴容
     allout=Arrays.copyOf(allout,allout.length+1);
     //將當前獲得的輸出流放入陣列中
     allout[allout.length-1]=pw;
    }
    System.out.println(hostname+"上線了當前上線人數"+allout.length);
    /*
     * 
     */
    while((words=br.readLine())!="over") {
     System.out.println(hostname+"<<"+words+";");
     //遍歷客戶端陣列向所有客戶端傳送資訊
     synchronized(allout) {
      for(int begin=0;begin<allout.length;++begin) {
       //除了自己向線上的所有人都傳送訊息
       if(allout[begin]!=pw)            
       allout[begin].println(hostname+"<<"+words);
       
      }
     }
    }
   }catch(SocketException e) {
    
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }finally {
    //對已經退出的使用者| 資料流 |進行刪除
    synchronized(allout) {
     for(int i=0;i<allout.length;i++) {
      if(allout[i]==pw) {
       allout[i]=allout[allout.length-1];
       allout=Arrays.copyOf(allout, allout.length-1);
       break;
      }
     }
    }
    try {
     socket.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   System.out.println(hostname+"下線了當前上線人數"+allout.length); 
  }
  
  
 }
}

相關文章