2012-10-05 71 views
1

我正嘗試創建一個使用線程來偵聽傳入消息的簡單聊天。我有一個主類打開一個服務器的套接字,目前只發送一條消息。雖然我在收聽收到的留言時遇到問題,但我無法弄清楚我做錯了什麼。Java聊天 - 從服務器偵聽線程

這是主要的類,對於所有的GUI代碼抱歉,它使它很長。

package def; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.PrintWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 

import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 
import javax.swing.UIManager; 
import javax.swing.border.EmptyBorder; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 


public class GUI extends JFrame { 

    private JPanel contentPane; 
    private JTextField textField; 

    private static JMenuBar menuBar; 
    private JMenu fileMenu; 
    private JMenuItem openMenu; 
    private JMenuItem exitMenu; 

    private Socket socket; 
    private ObjectOutputStream oos; 
    private ObjectInputStream ois; 

    private String ipAddress; 

    private JTextArea textArea; 
    private String fromServer = ""; 


    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       try { 
        GUI frame = new GUI(); 
        frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public GUI() throws IOException { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setBounds(100, 100, 450, 325); 
     contentPane = new JPanel(); 
     contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     contentPane.setLayout(new BorderLayout(0, 0)); 
     setContentPane(contentPane); 

     textArea = new JTextArea(); 
     contentPane.add(textArea, BorderLayout.NORTH); 
     textArea.setPreferredSize(new Dimension(0, 230)); 
     textArea.setEditable(false); 

     textField = new JTextField(); 
     textField.addKeyListener(new KeyAdapter() { 
      @Override 
      public void keyPressed(KeyEvent arg0) { 
       if(arg0.getKeyCode() ==java.awt.event.KeyEvent.VK_ENTER){ 
        // TODO 
       } 
      } 
     }); 
     contentPane.add(textField, BorderLayout.SOUTH); 
     textField.setColumns(10); 


     // Create menu item 
     menuBar = new JMenuBar(); 
     fileMenu = new JMenu("File"); 
     openMenu = new JMenuItem("Open chat"); 
     openMenu.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       ipAddress = JOptionPane.showInputDialog("Ange IP-address: "); 
       try { 
        openSocket(ipAddress); 
       } catch (UnknownHostException e) { 
        e.printStackTrace(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 

     exitMenu = new JMenuItem("Exit"); 
     exitMenu.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       System.exit(0); 
      } 
     }); 
     fileMenu.add(openMenu); 
     fileMenu.add(exitMenu); 
     menuBar.add(fileMenu); 

     setJMenuBar(menuBar); //Add the menubar 
     setVisible(true); 
    } 

    //Open a socket to the server 
    private void openSocket(String ipAddress) throws UnknownHostException, IOException { 
     socket = new Socket(ipAddress, 1337); 
     new ListenIncoming(socket, this).start(); 
     System.out.println("Socket and thread started!"); 
    } 

    public void setMessage(String message){ 
     textArea.setText(message); 
    } 
} 

在菜單中有一個「打開聊天」按鈕的動作偵聽器,它在其中運行方法openSocket()。在代碼的底部找到這個方法,我打開一個套接字並啓動一個新的ListenIncoming-thread。

這是線程的代碼:

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

public class ListenIncoming extends Thread{ 

    private Socket socket; 
    private ObjectInputStream ois; 
    private GUI gui; 


    public ListenIncoming(Socket socket, GUI gui){ 
     this.socket = socket; 
     this.gui = gui; 
    } 


    @Override 
    public void run() { 
     try { 
      ois = new ObjectInputStream(socket.getInputStream()); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 

     //A loop that runs forever 
     while(true){ 
      try { 
       String fromServer = ois.readObject().toString(); 
       System.out.println(fromServer); 
       gui.setMessage(fromServer); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

這是發送一個消息的服務器。我希望收到消息「連接」,但我什麼都沒有,沒有錯誤也沒有例外。我不知道我的代碼錯在哪裏。

public class Server { 

    private static Scanner in; 
    private static String toSend; 

    public static void main(String[] args) throws IOException { 
     toSend = ""; 
     int port = 1337; 
     in = new Scanner(System.in); 


     ServerSocket serverSocket = null; 
     try { 
      serverSocket = new ServerSocket(port); 
     } catch (IOException e) { 
      System.err.println("Could not listen on port: " + port); 
      System.exit(1); 
     } 

     Socket clientSocket = null; 
     try { 
      clientSocket = serverSocket.accept(); 
     } catch (IOException e) { 
      System.err.println("Could not connect."); 
      System.exit(1); 
     } 

     ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream()); 
     ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream()); 
     String input, output; 

     output = "Connected!\n"; 
     oos.writeObject(output); 
     System.out.println("This code is reached?"); 

     oos.close(); 
     ois.close(); 
     clientSocket.close(); 
     serverSocket.close(); 
    } 
} 

當我運行程序時,雖然我沒有從服務器類中獲得調試輸出,但我從GUI類中獲得了打印輸出。我正在使用Eclipse,但是不應該將這兩個類都寫入控制檯?我怎麼永遠達不到那個代碼?問題似乎是在服務器端,但是當嘗試讀取時,它不會在客戶端產生一些錯誤嗎?

感謝您提供的所有提示和輸入!

+0

既然你打開兩個java程序,會有兩個輸出控制檯。你有沒有檢查服務器的其他輸出控制檯? – sgpalit

+0

是不是防火牆阻止您在gui中輸入的服務器IP上的端口1337? –

+0

我之前沒有遇到過任何問題,只是現在當我使用不同的線程時。早些時候,我可以用一個while循環檢索發送的消息。 Eclipse中只有一個控制檯可以打開,我該如何打開另一個控制檯? 感謝您的意見! Z! –

回答

0

運行服務器類first..then您運行GUI類(客戶端)

打印在控制檯上確認服務器啓動 -

System.out.println("Server started: " + serverSocket); 

下面

serverSocket = new ServerSocket(port); 

以下行將等待客戶端連接到服務器。

socket = server.accept(); 

除非您無法獲取服務器消息。