Java聊天 - 从服务器监听的线程

时间:2012-10-05 13:37:57

标签: java multithreading sockets

我尝试创建一个使用线程侦听传入消息的简单聊天。我有一个主类打开一个服务器的套接字,目前只发送一条消息。我虽然在收听传入的消息时遇到问题,但我无法弄清楚我做错了什么。

这是主要的类,对所有的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();
            }
        }
    }
}

这是发送一条消息的服务器。我希望收到消息" Connected"但我什么都没得到,没有错误也没有例外。我不知道我的代码出错了。

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,但这两个类都不能写入控制台吗?为什么我永远不会达到那个代码?这个问题似乎是在服务器端,但在尝试阅读时,它不会在客户端产生一些错误吗?

感谢您提供的所有提示和输入!

1 个答案:

答案 0 :(得分:0)

首先运行Server类..然后运行GUI类(客户端)

在控制台上打印以确认服务器已启动 -

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

下面

serverSocket = new ServerSocket(port); 

以下行将等待客户端连接到服务器。

    socket = server.accept();

除非您无法获取服务器消息。