我正嘗試創建一個使用線程來偵聽傳入消息的簡單聊天。我有一個主類打開一個服務器的套接字,目前只發送一條消息。雖然我在收聽收到的留言時遇到問題,但我無法弄清楚我做錯了什麼。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,但是不應該將這兩個類都寫入控制檯?我怎麼永遠達不到那個代碼?問題似乎是在服務器端,但是當嘗試讀取時,它不會在客戶端產生一些錯誤嗎?
感謝您提供的所有提示和輸入!
既然你打開兩個java程序,會有兩個輸出控制檯。你有沒有檢查服務器的其他輸出控制檯? – sgpalit
是不是防火牆阻止您在gui中輸入的服務器IP上的端口1337? –
我之前沒有遇到過任何問題,只是現在當我使用不同的線程時。早些時候,我可以用一個while循環檢索發送的消息。 Eclipse中只有一個控制檯可以打開,我該如何打開另一個控制檯? 感謝您的意見! Z! –