首页 文章

java - 如何在lan上连接客户端和服务器?

提问于
浏览
0

这是thenewboston的java即时通讯程序的(稍微)修改版本 .

然而,似乎存在问题 . 如果我在同一设备上运行服务器和客户端它正常工作,但如果客户端在另一台PC(本地)上则无法连接 .

P.S我对网络,流和套接字知之甚少,所以请记住这一点 .

编辑:一切都是固定的,从客户端使用错误的IP地址!

//SERVER
public class Server {

private JFrame                 frame;
private JTextField             userText;
private JTextArea              textArea;
private ObjectOutputStream     output;
private ObjectInputStream      input;
private ServerSocket           server;
private Socket                 connection;
private boolean                userTerminatedConnection = false;
private static final int PORT = 6789;
public static void main(String[] args) {
     Server window = new Server();
     window.frame.setVisible(true);
     window.startServer();
}


public Server() {
    initialize();
}

private void initialize() {
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1){}
    frame = new JFrame("SERVER");
    frame.setBounds(300, 300, 318, 338);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    userText = new JTextField();
    frame.getContentPane().add(userText, BorderLayout.SOUTH);
    userText.setEditable(false);
    userText.setColumns(10);
    userText.addActionListener(new
            ActionListener(){
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    sendMessage(arg0.getActionCommand());
                    userText.setText(null);


                }



    }
            );

    textArea = new JTextArea();
    textArea.setEditable(false);
    textArea.setFont(new Font("Monospaced", Font.PLAIN, 15));
    frame.getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER);
}

public void startServer(){
    try{
        server = new ServerSocket(PORT);
        System.out.println(InetAddress.getLocalHost().getHostAddress());
        while(true){
            try{
                waitForConnection();
                setupStreams();
                whileChatting();
            }catch(EOFException e){
                showMessage("\nSERVER TERMINATED CONNECTION");
            }finally{
                closeAll();
            }
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}





private void whileChatting() throws IOException{
    String message ="You are now connected !";
    sendMessage(message);
    ableToType(true);
    do{
        try{
            message = (String) input.readObject();
            showMessage("\n"+message);
        }catch(ClassNotFoundException e){
            showMessage("\n UNRECOGNISED OBJECT");
        }catch(SocketException ex){
            userTerminatedConnection = true;
        }
    }while(!message.endsWith("ENDCONN") && !userTerminatedConnection);
    userTerminatedConnection = false;
}


private void setupStreams() throws IOException{
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();
    input = new ObjectInputStream(connection.getInputStream());
}


private void waitForConnection() throws IOException {
  showMessage("Waiting for connection...\n");
  connection = server.accept();
  showMessage("Now connected to "+connection.getInetAddress().getHostName());
}

private void closeAll() {
    showMessage("\nClosing connection \n");
    ableToType(false);
    try{
        input.close();
        output.close();
        connection.close();
    }catch(IOException e){

    }
}

private void ableToType(final boolean b) {
    SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    userText.setEditable(b);
                }
            }
    );
}


private void sendMessage(String string) {
    try{
        output.writeObject("SERVER - "+string);
        output.flush();
        showMessage("\nSERVER - "+string);
    }catch(IOException e){
        textArea.append("\nCANT SEND");
    }

}


private void showMessage(final String string) {
    SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    textArea.append(string);
                }
            }
    );

}

 }




 //CLIENT



 public class Client {

private JFrame                frame;
private JTextField            userText;
private JTextArea             chatBox;
private ObjectOutputStream    output;
private ObjectInputStream     input;
private String                message;
private String                serverIP;
private Socket                connection;
private boolean               isConnected = false;
private String                clientName = "CLIENT";

public static void main(String[] args) throws IOException {
     Client window = new Client();
     window.frame.setVisible(true);
     window.clientName = JOptionPane.showInputDialog(null, "Enter client nickname");
     String ipEntered = JOptionPane.showInputDialog(null, "Enter the ip address to establish connection !");

     if(ipEntered.equals("localhost")||ipEntered.equals("")){
         ipEntered = "127.0.0.1";
     }

     if(window.clientName.equals("")){
         window.clientName = "CLIENT";
     }

     if(window.clientName.toCharArray().length > 15){
         window.clientName = "CLIENT";
     }

     window.setHostIp(ipEntered);
     window.startClient();
}


public Client() {
    initialize();
}

private void setHostIp(String host){
    serverIP = host;
}
private void initialize() {
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1){}
    frame = new JFrame("Client");
    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosed(WindowEvent arg0) {
            if(isConnected)
            closeAll();
        }
    });
    frame.setBounds(100, 100, 318, 338);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    chatBox = new JTextArea();
    chatBox.setFont(new Font("Monospaced", Font.PLAIN, 15));
    frame.getContentPane().add(new JScrollPane(chatBox), BorderLayout.CENTER);

    userText = new JTextField();
    userText.setFont(new Font("Tahoma", Font.PLAIN, 11));
    userText.setEditable(false);
    frame.getContentPane().add(userText, BorderLayout.SOUTH);
    userText.setColumns(10);
    userText.addActionListener(
         new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent arg0) {
                sendData(arg0.getActionCommand());
                userText.setText("");
            }



         }
    );

}
private void startClient() throws IOException{
    try{
        connectToServer();
        setupStreams();
        whileChatting();
        isConnected = true;
    }catch(EOFException ex){
        showMessage("\nClient terminated connection");
    }finally{
        if(isConnected)
        closeAll();
        else
            System.exit(0);
    }
}


private void connectToServer() throws IOException{
    showMessage("\nAttempting connection");
    connection = new Socket(InetAddress.getByName(serverIP),6789);
    showMessage("\nConnected to :"+connection.getInetAddress().getHostName());

}

private void setupStreams() throws IOException {
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();
    input = new ObjectInputStream(connection.getInputStream()); 
}

private void whileChatting() throws IOException{
    ableToType(true);
    do{
        try{
            message = (String) input.readObject();
            showMessage("\n"+message);
        }catch(ClassNotFoundException e){
            showMessage("UNRECOGNISED OBJECT");
        }
    }while(!message.equals("SERVER - ENDCONN"));
}

private void closeAll() {
    showMessage("\nClosing stuff");
    ableToType(false);
    try{
        output.close();
        input.close();
        connection.close();
    }catch(IOException e){

    }
    System.exit(0);
}



private void sendData(String mess) {
    try{
        output.writeObject(clientName+" - "+mess);
        showMessage("\n"+clientName+" - "+mess);
    }catch(IOException e){
        chatBox.append("\nSomething went wrong");
    }

}
private void showMessage(String string) {
    SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    chatBox.append(string);
                }
            }
    );

}
private void ableToType(final boolean b) {
    SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    userText.setEditable(b);
                }
            }
    );
}

 }

1 回答

  • 0

    问题是这个方法: waitForConnection(); ,最终会阻塞整个流程,以便它可以等待传入连接并在它们到来时处理它们 .

    您需要做的是确保传入连接的等待和处理是在单独的线程上完成的,以确保您不会阻止当前的应用程序 .

    编辑:.accept()方法阻止您的主线程,直到新连接到达 . 通常所做的事情(取决于您正在构建的服务器的类型)是 .accept 部分是在一个单独的线程中完成的 . 你需要这个,以便在另一个线程上完成等待,并且你不会阻止你的主线程 .

    现在,有些情况出现了回应需要时间 . 为了解决这个问题,响应的构造和传输也是在一个单独的线程中完成的,以便现在影响新的请求 .

    如果这不是一个要求(您可以等待几秒钟以获得响应,或者如果您可以相对快地构建响应,或者您将拥有相对较少的客户端数量),那么您可以在不创建新的情况下完成线程以满足传入的请求,并创建一个等待传入连接的线程 .

相关问题