2017-02-27 56 views
0

這是newboston的java即時通訊程序的一個(略)修改版本。java - 如何連接局域網上的客戶端和服務器?

但是似乎存在問題。 如果我在同一臺設備上運行服務器和客戶端,它工作正常,但如果客戶端在另一臺電腦(本地)上,則無法連接。

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); 
       } 
      } 
    ); 
} 

} 
+0

端口6789是否阻塞到外部連接。在任何一臺機器上啓動服務器,然後從命令提示符運行「nestat -an」並共享結果。 –

+0

由於您沒有明確指定綁定地址,因此服務器將綁定到所有可用的網絡接口,即默認情況下它將能夠遠程訪問 –

+0

netstat -an爲端口6789提供了以下結果:LISTENING – Vlad

回答

0

的問題是,這種方法:waitForConnection();,最終塊你的整個流程,以便它可以等待傳入連接並處理他們,當他們來了。

您需要做的是確保等待並處理傳入連接在單獨的線程上完成,以確保您不會阻止當前的應用程序。

編輯: .accept()方法阻塞您的主線程,直到一個新的連接到達。通常完成的工作(取決於您正在構建的服務器的類型)是.accept部分是在單獨的線程中完成的。您需要這樣做,以便在另一個線程上完成等待,並且不會阻止您的主線程。

現在,有一些場景提出了一個響應可能需要時間。爲了解決這個問題,響應的構建和傳輸也是在單獨的線程中完成的,以便現在影響新的請求。如果這不是要求(您可以等待幾秒鐘以獲得響應,或者如果您可以構建響應速度相對較快,或者您的客戶端數量相對較少),那麼您可以在沒有創建一個新的線程來迎合傳入的請求,並創建一個等待傳入連接的線程。

+0

你是說我應該把整個waitForConnection()方法放到一個線程中?或者建立單獨的方法來等待和處理連接? – Vlad

+0

@Vlad:我已經更新了我的答案。 – npinti

+0

在我的情況下,我真的不需要快速響應,也沒有多個客戶端,但問題是,當我把waitForConnection()方法的內容放入一個線程時,程序返回一個錯誤,可能是因爲它試圖在連接之前進行連接成立。 – Vlad

相關問題