2015-02-08 48 views
1

我一直在服務器 - 客戶端聊天應用程序中使用「googeling」很長時間,但我無法真正理解它們。他們中的許多人正在使用一個類並從中創建GUI,我不想直接從它那裏複製。很多示例並沒有真正解釋如何將消息從客戶端發送到服務器,然後將消息發送給所有其他客戶端。JAVA上的服務器 - 客戶端聊天應用上的示例

我正在使用NetBeans,我想知道是否有一些很好的tutourials或例子可以幫助我呢?

+1

提取所需的代碼並將其放到App.java的'main'中。此外,這不是要求教程或示例,但具體編程問題的網站。 – ChiefTwoPencils 2015-02-08 22:12:35

回答

0

這裏談到的多線程程序:)服務器有兩個類,客戶端有一個。希望你喜歡!

服務器主類:

import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 


public class Main { 

    public static void main(String[] args) throws IOException { 
     int MAXCLIENTS = 20; 
     int port = 4444; 
     ServerSocket server = null; 
     Socket clientSocket = null; 
     // An array of clientsConnected instances 
     ClientThread[] clientsConnected = new ClientThread[MAXCLIENTS]; 

     try { 
      server = new ServerSocket(port); 
      System.out.println("listening on port: " + port); 
     } catch (IOException e) {// TODO Auto-generated catch block 
      e.printStackTrace(); 

     } 

     while (true) { 
      try { 
       clientSocket = server.accept(); 

      } catch (IOException e) { 
       e.printStackTrace(); 
       if (!server.isClosed()){server.close();} 
       if (!clientSocket.isClosed()){clientSocket.close();} 
      } 

      System.out.println("Client connected!"); 

      for (int c = 0; c < clientsConnected.length; c++){ 
       if (clientsConnected[c] == null){ 
        // if it is empty (null) then start a new Thread, and pass the socket and the object of itself as parameter 
        (clientsConnected[c] = new ClientThread(clientSocket, clientsConnected)).start(); 
        break; // have to break, else it will start 20 threads when the first client connects :P 
       } 
      } 
     } 

    } 



} 

服務器的客戶端類:

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 


public class ClientThread extends Thread{ 

    private ClientThread[] clientsConnected; 
    private Socket socket = null; 
    private DataInputStream in = null; 
    private DataOutputStream out = null; 
    private String clientName = null; 

    //Constructor 
    public ClientThread(Socket socket, ClientThread[] clientsConnected){ 
     this.socket = socket; 
     this.clientsConnected = clientsConnected; 
    } 

    public void run(){ 
     try { 
      // Streams :) 
      in = new DataInputStream(socket.getInputStream()); 
      out = new DataOutputStream(socket.getOutputStream()); 

      String message = null; 

      clientName = in.readUTF(); 

      while (true){ 
       message = in.readUTF(); 

       for (int c = 0; c < clientsConnected.length; c++){ 
        if (clientsConnected[c]!= null && clientsConnected[c].clientName != this.clientName){ //dont send message to your self ;) 
         clientsConnected[c].sendMessage(message, clientName); // loops through all the list and calls the objects sendMessage method. 
        } 
       } 

      } 

     } catch (IOException e) { 
      System.out.println("Client disconnected!"); 
      this.clientsConnected = null; 
     } 
    } 
    // Every instance of this class (the client) will have this method. 
    private void sendMessage(String mess, String name){ 
     try { 
      out.writeUTF(name + " says: " + mess); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

終於客戶端:

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 
import java.util.Scanner; 

public class Main 
{ 
    public static void main(String[] args) throws IOException { 

     Main m = new Main(); 
     m.connect(); 
    } 

    public void connect() throws IOException{ 
    //declare a scanner so we can write a message 
     Scanner keyboard = new Scanner(System.in); 


     // localhost ip 
     String ip = "127.0.0.1"; 
     int port = 4444; 
     Socket socket = null; 

     System.out.print("Enter your name: "); 
     String name = keyboard.nextLine(); 

     try { 

     //connect 
     socket = new Socket(ip, port); 

     //initialize streams 
     DataInputStream in = new DataInputStream(socket.getInputStream()); 
     DataOutputStream out = new DataOutputStream(socket.getOutputStream()); 

     //start a thread which will start listening for messages 
     new ReceiveMessage(in).start(); 

     // send the name to the server! 
     out.writeUTF(name); 

     while (true){ 
      //Write messages :) 
      String message = keyboard.nextLine(); 
      out.writeUTF(message); 
     } 

     } 
     catch (IOException e){ 
      e.printStackTrace(); 
      if (!socket.isClosed()){socket.close();} 
     } 
    } 

    class ReceiveMessage extends Thread{ 

     DataInputStream in; 

     ReceiveMessage(DataInputStream in){ 
      this.in = in; 
     } 

     public void run(){ 
      String message; 
      while (true){ 
       try { 
        message = in.readUTF(); 
        System.out.println(message); 

       } catch (IOException e) { 
       e.printStackTrace(); 
       } 

      } 
     } 

    } 

} 

我跑在Eclipse中的服務器,並開始從兩個客戶端CMD,看起來像這樣:

enter image description here

+0

非常感謝!希望我會更多地瞭解這個以及它如何與多線程一起工作!非常感謝花時間這樣做。我會做這個,然後嘗試實現它的GUI!再次感謝你,你搖滾! – Bojje 2015-02-09 08:39:29

+0

聽起來不錯!歡迎您:) – Johan 2015-02-09 10:26:04

+0

我試圖找到一種方法來發送PM,但我無法找到如何去做,所以我不得不在這裏問。在第一個Class Server中(稱爲main)在for循環中檢查數組中是否有客戶端,如果不是,則只需創建一個客戶端。你不應該在每次套接字被接受時在列表中創建並添加一個客戶端嗎?對我來說,它看起來像服務器只能接受一個客戶端。 – Bojje 2015-02-09 18:36:57

0

這是一個超級簡單的,我剛纔提出了一些關於正在發生的事情的評論。連接到服務器的客戶端可以鍵入服務器將打印出來的消息。這不是聊天程序,因爲服務器接收消息,客戶端發送它們。但希望你會更好地瞭解它更好:)

服務器:

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 


public class Main { 

    public static DataInputStream in; 
    public static DataOutputStream out; 

    public static void main(String[] args) throws IOException { 


    int port = 4444; 
    ServerSocket server = null; 
    Socket clientSocket = null; 

    try { 

    //start listening on port 
    server = new ServerSocket(port); 

    System.out.println("Listening on port: " + port); 

    //Accept client 
    clientSocket = server.accept(); 

    System.out.println("client Connected!"); 

    //initialize streams so we can send message 
    in = new DataInputStream(clientSocket.getInputStream()); 
    out = new DataOutputStream(clientSocket.getOutputStream()); 

    String message = null; 

     while (true) { 
      // as soon as a message is being received, print it out! 
      message = in.readUTF(); 
      System.out.println(message); 
     } 

    } 
    catch (IOException e){ 
     e.printStackTrace(); 
     if (!server.isClosed()){server.close();} 
     if (!clientSocket.isClosed()){clientSocket.close();} 
    } 

    } 

} 

客戶:

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 
import java.util.Scanner; 

public class Main 
{ 
    public static void main(String[] args) throws IOException { 

     //declare a scanner so we can write a message 
     Scanner keyboard = new Scanner(System.in); 


     // localhost ip 
     String ip = "127.0.0.1"; 
     int port = 4444; 
     Socket socket = null; 

     try { 

     //connect 
     socket = new Socket(ip, port); 

     //initialize streams 
     DataInputStream in = new DataInputStream(socket.getInputStream()); 
     DataOutputStream out = new DataOutputStream(socket.getOutputStream()); 


     while (true){ 
      System.out.print("\nMessage to server: "); 
      //Write a message :) 
      String message = keyboard.nextLine(); 
      //Send it to the server which will just print it out 
      out.writeUTF(message); 
     } 

     } 
     catch (IOException e){ 
      e.printStackTrace(); 
      if (!socket.isClosed()){socket.close();} 
     } 
    } 
} 
+0

謝謝你的例子:)一個問題是,如果我運行2個客戶端實例,他們是否能夠聽到對方?意思是如果我先運行client1然後再運行client2,client1會聽到client2發送給服務器的內容嗎? – Bojje 2015-02-08 23:12:21

+0

不客氣,對不起,但是這個服務器只需要一個客戶端,如果一個服務器想要處理多個客戶端,那麼你應該使用多線程。 – Johan 2015-02-08 23:17:51

+0

是的,我一直在看。創建客戶端類的對象並將它們作爲線程運行。但我不知道如何讓他們在服務器上互相傾聽。 – Bojje 2015-02-08 23:22:00

相關問題