スレッドを使用して着信メッセージをリッスンする簡単なチャットを作成しようとしています。現時点では1つのメッセージのみを送信するサーバーへのソケットを開くメインクラスがあります。ただし、着信メッセージをリッスンするのに問題があり、何が間違っているのかわかりません。
これはメイン クラスです。すべての 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 スレッドを開始します。
これはスレッドコードです:
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();
}
}
}
}
これは、1 つのメッセージを送信するサーバーです。「接続済み」というメッセージが表示されるはずでしたが、何も表示されず、エラーも例外もありません。コードのどこが間違っているのかわかりません。
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 クラスから出力が得られますが、Server クラスからはデバッグ出力が出力されません。私は Eclipse を使用していますが、両方のクラスがコンソールに書き込めるようにすべきではありませんか? なぜそのコードに到達しないのですか? 問題はサーバー側にあるようですが、クライアント側で読み込もうとすると何らかのエラーが発生するのではないでしょうか?
これについて私が得ることができるすべてのヒントと情報をありがとう!