如何设置我的Java聊天室程序以使用端口转发?

时间:2015-08-20 06:48:56

标签: java networking chatroom

我看了一个关于简单Java网络的教程,教程显示服务器和客户端应用程序在同一台计算机上运行并且工作正常,我想知道是否有办法让它在使用端口转发的不同家庭中的不同计算机上运行或者是其他东西;这是我的代码:

Server.java:

package com.cloud.server;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * The Server class extends JFrame and contains all of the code pertaining to the GUI and the server
 * 
 * @author mcjcloud
 *
 */

public class Server extends JFrame
{
    private JTextField userInput;
    private JTextArea convo;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private ServerSocket server;        // establishes server
    private Socket connection;          // establishes connection with other computer

    /**
     * Constructor (basically just sets up the GUI and actionListener(s)
     */
    public Server()
    {
        super("Cloud Messenger");

        userInput = new JTextField();
        userInput.setEditable(false);
        userInput.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e) 
            {
                sendMessage(e.getActionCommand());
                userInput.setText("");
            }
        });
        add(userInput, BorderLayout.SOUTH);

        // set up convo (JTextArea)
        convo = new JTextArea();
        add(new JScrollPane(convo));
        setSize(500, 700);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    /**
     * startServer() method waits for connection, sets up connection and manages chat
     */
    public void startServer()
    {
        try
        {
            server = new ServerSocket(6789, 100, InetAddress.getByName("0.0.0.0")); // (port number, backlog) backlog (aka qlength) = "how many people can connect at a time"
            while(true) // infinite loop
            {
                try
                {
                    waitForConnection();    // first set up the connection
                    setupStreams();         // set up the streams
                    chat();                 // enable the chat and things
                }
                catch(EOFException eofe)    // EOF = EndOfStream (meaning the input/output stream ended)
                {
                    showMessage("Connection terminated.");
                }
                finally
                {
                    cleanUpConnection();
                }
            }
        }
        catch(IOException io)
        {
            io.printStackTrace();
        }
    }

    /**
     * waitForConnection() method will wait for the connection, then display connection info
     * 
     * @throws IOException
     */
    private void waitForConnection() throws IOException
    {
        showMessage("Waiting for connection...");
        connection = server.accept();       // listens for a connection
        showMessage("Now connected to " + connection.getInetAddress().getHostName());
    }

    /**
     * setupStream() method gets a stream to send/recieve data
     */
    private void setupStreams() throws IOException
    {
        // setup output stream
        output = new ObjectOutputStream(connection.getOutputStream());  // create pathway to allow us to connect to the computer the socket is connected to
        output.flush();

        // setup input stream
        input = new ObjectInputStream(connection.getInputStream()); // create pathway to receive messages
        showMessage("Stream setup success.");
    }

    /**
     * chat() method code runs during conversation
     */
    private void chat() throws IOException
    {
        String message = "Chatting enabled";
        showMessage(message);
        setCanType(true);
        do
        {
            try
            {
                message = (String) input.readObject();
                showMessage(message);
            }
            catch(ClassNotFoundException cnfe)
            {
                showMessage("Message recieve failed (Other person's problem)");
            }
        }
        while(!message.equals("CLIENT - /terminate"));
    }

    /**
     * cleanUpConnection() method cleans up the stream and things after the chat has ended
     */
    private void cleanUpConnection()
    {
        showMessage("Closing connection...");
        setCanType(false);
        try
        {
            output.close();
            input.close();
            connection.close();
        }
        catch(IOException io)
        {
            io.printStackTrace();
        }
    }

    /**
     * sendMessage(String) method sends whatever message you type
     * 
     * @param message is what is going to be shown
     */
    private void sendMessage(String message)
    {
        try
        {
            output.writeObject("SERVER - " + message);  // write the message to the outputstream
            output.flush();
            showMessage("SERVER - " + message);
        }
        catch(IOException io)
        {
            convo.append("ERROR: Message can't be sent.");
        }
    }

    /**
     * showMessage(String)shows whatever needs to be shown on the JTextArea
     */
    private void showMessage(String message)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                convo.append(" " + message + "\n");
            }
        });
    }

    /**
     * setCanType() method decides whether or not a user can type
     * 
     * @param canType
     */
    private void setCanType(boolean canType)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                userInput.setEditable(canType);
            }
        });
    }

}

InvokeServer.java:

package com.cloud.server;

import javax.swing.JFrame;

public class InvokeServer 
{
    public static void main(String[] args)
    {
        Server server = new Server();
        server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        server.startServer();
    }

}

Client.java:

package com.cloud.client;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * Client class is the sister of the Server class in the server application, contains all the code to build GUI and send info to server and receive
 * 
 * @author mcjcloud
 *
 */
public class Client extends JFrame
{
    private JTextField userInput;
    private JTextArea convo;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private String message = "";
    private String serverIP;        // connecting to a specific server
    private Socket connection;

    public Client(String host)
    {
        super("Cloud Messenger");
        serverIP = host;

        userInput = new JTextField();
        userInput.setEditable(false);
        userInput.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e) 
            {
                sendMessage(e.getActionCommand());
                userInput.setText("");
            }
        });
        add(userInput, BorderLayout.SOUTH);

        convo = new JTextArea();
        add(new JScrollPane(convo));
        setSize(500, 700);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    /**
     * startClient() method invokes the whole conversation 
     */
    public void startClient()
    {
        try
        {
            boolean connected = false;
            showMessage("Connecting to server...");
            while(!connected)
            {
                try
                {
                    connected = connectToServer();
                }
                catch(ConnectException ce)
                {
                    // do nothing
                }
            }
            setupStreams();
            chat();
        }
        catch(EOFException eofe)
        {
            sendMessage("Connection terminated.");
        }
        catch(IOException ioe)
        {
            ioe.printStackTrace();
        }
        finally
        {
            cleanUpConnection();
        }
    }

    /**
     * connectToServer() establishes connection with the server application
     * 
     * @throws IOException
     */
    private boolean connectToServer() throws IOException
    {
        connection = new Socket(InetAddress.getByName(serverIP), 6789);
        showMessage("Now connected to " + connection.getInetAddress().getHostName());
        return true;
    }

    /**
     * setupStream() method gets a stream to send/recieve data
     */
    private void setupStreams() throws IOException
    {
        // setup output stream
        output = new ObjectOutputStream(connection.getOutputStream());  // create pathway to allow us to connect to the computer the socket is connected to
        output.flush();

        // setup input stream
        input = new ObjectInputStream(connection.getInputStream()); // create pathway to receive messages
        showMessage("Stream setup success.");
    }

    /**
     * chat() method code runs during conversation
     */
    private void chat() throws IOException
    {
        String message = "Chatting enabled";
        showMessage(message);
        setCanType(true);
        do
        {
            try
            {
                message = (String) input.readObject();
                showMessage(message);
            }
            catch(ClassNotFoundException cnfe)
            {
                showMessage("Message recieve failed (Other person's problem)");
            }
        }
        while(!message.equals("SERVER - /terminate"));
    }

    /**
     * cleanUpConnection() method cleans up the stream and things after the chat has ended
     */
    private void cleanUpConnection()
    {
        showMessage("Closing connection...");
        setCanType(false);
        try
        {
            output.close();
            input.close();
            connection.close();
        }
        catch(IOException io)
        {
            io.printStackTrace();
        }
    }

    /**
     * sendMessage(String) method sends whatever message you type
     * 
     * @param message is what is going to be shown
     */
    private void sendMessage(String message)
    {
        try
        {
            output.writeObject("CLIENT - " + message);  // write the message to the outputstream
            output.flush();
            showMessage("CLIENT - " + message);
        }
        catch(IOException io)
        {
            convo.append("ERROR: Message can't be sent.");
        }
    }

    /**
     * showMessage(String) shows whatever needs to be shown on the JTextArea
     */
    private void showMessage(String message)
    {
        SwingUtilities.invokeLater(new Runnable()   // USE THIS RUNNABLE TO UPDATE GUI
        {
            public void run()
            {
                convo.append(" " + message + "\n");
            }
        });
    }

    /**
     * setCanType() method decides whether or not a user can type
     * 
     * @param canType
     */
    private void setCanType(boolean canType)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                userInput.setEditable(canType);
            }
        });
    }

}

InvokeClient.java:

package com.cloud.client;

import javax.swing.JFrame;

public class InvokeClient 
{
    public static void main(String[] args)
    {
        Client client = new Client("99.25.233.116");
        client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.startClient();
    }

}

注意: 我尝试在我的家庭网络上使用端口6789在我的一台笔记本电脑上设置端口转发,这就是我运行服务器应用程序的笔记本电脑。

1 个答案:

答案 0 :(得分:0)

我解决了。我刚刚撤消并重新启动了端口转发,它使用了公共IP地址。谢谢大家的帮助