2016-10-20 4 views
1

Ich habe eine grundlegende Chat-App. Es gibt 3 Klassen: Server, Client und ClientHandler. Das Problem besteht darin, dass der Server nur beim ersten Mal lesen kann (mit DataInputStream) und dann Ausnahmen auslöst.Java DataOutputSream funktioniert nur einmal

Hello. I have a basic chat app. There are 3 classes: server, client and clientHandler. The problem is that server is able to read (using DataInputStream) only first time then it throws exceptions. 

Client.java:

package Client; 

import javax.swing.JFrame; 

import javax.swing.JPanel; 
import javax.swing.border.EmptyBorder; 
import javax.swing.JTextArea; 

import javax.swing.JButton; 
import javax.swing.JTextField; 
import java.awt.event.ActionListener; 

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 

import java.net.Socket; 
import java.net.UnknownHostException; 
import java.awt.event.ActionEvent; 
import javax.swing.JScrollPane; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 


public class Client extends JFrame{ 

private JPanel contentPane; 
private JTextField tf_input; 
private static JTextArea ta_chat; 
private JButton b_connect; 


private static int portNumber = 2309; 
private static String ip = null; 
private JScrollPane scrollPane; 
private JTextField tf_ip; 


private Socket s = null; 
private DataOutputStream dos = null; 
private DataInputStream dis = null; 
private JTextField tf_port; 


private boolean connected = false; 
private JLabel lblIp; 
private JLabel lblPort; 
private JLabel lblName; 
private JTextField tf_name; 
private JButton btnDc; 


/** 
* Launch the application. 
*/ 
public static void main(String[] args) { 

    Client frame = new Client(); 
    frame.setVisible(true); 


    System.out.println("Client is running!"); 


    // TODO Auto-generated method stub 



    //Listening to server 

    while(!frame.connected) 
    { 
     System.out.println("Waiting...!"); 
    } 

    while(true) 
    { 
     System.out.println("Listening started!"); 
     String line = null; 

     try { 
      line = frame.dis.readUTF(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
      ta_chat.append("reading from server failed\n"); 
      //System.out.println(Thread.currentThread().getName() + " failed listening to server!\n"); 
     } 

     if(line!=null) 
      ta_chat.append(line.trim() + "\n"); 
    } 
} 

    // 


/** 
* Create the frame. 
*/ 
public Client() { 
    setTitle("Client"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 530, 458); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    setContentPane(contentPane); 
    contentPane.setLayout(null); 

    JButton b_send = new JButton("Send"); 
    b_send.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      if(!connected) 
      { 
       JOptionPane.showMessageDialog(null, "You have to connect first!"); 
       return; 
      } 

      String message = tf_input.getText(); 

      try { 
       ta_chat.append("writing UTF" + '\n'); 
       dos.writeUTF(message); 
       ta_chat.append(ta_chat.getText().trim() + "writing UTF succeded" + '\n'); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       ta_chat.append(ta_chat.getText().trim() + "writing UTF failed" + '\n'); 
      } 

      tf_input.setText(null); 
     } 
    }); 
    b_send.setBounds(375, 204, 89, 23); 
    contentPane.add(b_send); 

    tf_input = new JTextField(); 
    tf_input.setBounds(89, 205, 258, 20); 
    contentPane.add(tf_input); 
    tf_input.setColumns(10); 

    scrollPane = new JScrollPane(); 
    scrollPane.setBounds(39, 11, 452, 175); 
    contentPane.add(scrollPane); 

    ta_chat = new JTextArea(); 
    scrollPane.setViewportView(ta_chat); 
    ta_chat.setEditable(false); 

    b_connect = new JButton("Connect"); 
    b_connect.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent ae) { 

      connected = true; 

      String ip = tf_ip.getText(); 
      String name = tf_name.getText(); 
      int portNumber = Integer.parseInt(tf_port.getText()); 

      try { 
       s = new Socket(ip, portNumber); 
       ta_chat.append("s=" + s + "\n"); 
      } catch (UnknownHostException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      try { 
       dis = new DataInputStream(s.getInputStream()); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       ta_chat.append("dis init failed\n"); 
      } 

      try { 
       dos = new DataOutputStream(s.getOutputStream()); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       System.out.println("DataOutputStraem object init failed!"); 
       ta_chat.append("dos init failed\n"); 
      } 

      try 
      { 
       dos.writeUTF("/name " + name); 
      } 
      catch(Exception e) 
      { 
       ta_chat.append("dos.writeUTF() failed \n"); 
      } 
     } 
    }); 
    b_connect.setBounds(89, 373, 89, 23); 
    contentPane.add(b_connect); 

    tf_ip = new JTextField(); 
    tf_ip.setBounds(83, 269, 123, 20); 
    contentPane.add(tf_ip); 
    tf_ip.setColumns(10); 

    tf_port = new JTextField(); 
    tf_port.setColumns(10); 
    tf_port.setBounds(83, 300, 123, 20); 
    contentPane.add(tf_port); 

    lblIp = new JLabel("IP:"); 
    lblIp.setBounds(39, 272, 46, 14); 
    contentPane.add(lblIp); 

    lblPort = new JLabel("Port"); 
    lblPort.setBounds(39, 303, 46, 14); 
    contentPane.add(lblPort); 

    lblName = new JLabel("Name:"); 
    lblName.setBounds(39, 335, 46, 14); 
    contentPane.add(lblName); 

    tf_name = new JTextField(); 
    tf_name.setColumns(10); 
    tf_name.setBounds(83, 332, 123, 20); 
    contentPane.add(tf_name); 

    btnDc = new JButton("dc"); 
    btnDc.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      try { 
       dis.close(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      try { 
       dos.close(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      try { 
       s.close(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }); 
    btnDc.setBounds(290, 373, 89, 23); 
    contentPane.add(btnDc); 

} 

}

Server.java:

package Server; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.InetAddress; 
import java.net.MalformedURLException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.URL; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 
import javax.swing.border.EmptyBorder; 

public class Server extends JFrame{ 

private JPanel contentPane; 
private JTextField tf_input; 

private static int portNumber = 2309; 
private static JTextArea ta_ServerLog; 
private JTextField tf_IP; 
private JButton btnRefresh; 
private JTextField textField; 
private JLabel lblPort; 
private static ServerSocket ss = null; 

/** 
* Launch the application. 
*/ 

public static void addTextToServerLog(String text) 
{ 
    if(text.equals(null)) 
     return; 
    else 
     ta_ServerLog.setText(ta_ServerLog.getText().trim() + "\n" + text.trim()); 
} 

public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       Server frame = new Server(); 
       frame.setVisible(true); 
      } catch (Exception e) { 

      } 
     } 
    }); 


    try { 
     ss = new ServerSocket(portNumber); 
    } catch (IOException e1) { 
     // TODO Auto-generated catch block 
    } 


    while(true) 
    { 
     Socket s = null; 
     try { 
      s = ss.accept(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 

     } 

     System.out.println("Creating new ClientListener!"); 
     new ClientHandler(s).start(); 
    } 

} 

/** 
* Create the frame. 
*/ 
public Server() { 
    setTitle("Server"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 450, 377); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    setContentPane(contentPane); 
    contentPane.setLayout(null); 

    tf_input = new JTextField(); 
    tf_input.setBounds(125, 209, 109, 20); 
    contentPane.add(tf_input); 
    tf_input.setColumns(10); 

    JButton b_send = new JButton("Send"); 
    b_send.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     } 
    }); 
    b_send.setBounds(278, 209, 86, 20); 
    contentPane.add(b_send); 

    JScrollPane scrollPane = new JScrollPane(); 
    scrollPane.setBounds(49, 26, 294, 136); 
    contentPane.add(scrollPane); 

    ta_ServerLog = new JTextArea(); 
    ta_ServerLog.setEditable(false); 
    scrollPane.setViewportView(ta_ServerLog); 

    JLabel lblYouAreHosting = new JLabel("Your IP:"); 
    lblYouAreHosting.setBounds(49, 277, 44, 14); 
    contentPane.add(lblYouAreHosting); 

    tf_IP = new JTextField(); 
    tf_IP.setEditable(false); 
    tf_IP.setBounds(96, 274, 103, 20); 
    contentPane.add(tf_IP); 
    tf_IP.setColumns(10); 

    btnRefresh = new JButton("Refresh IP"); 
    btnRefresh.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      tf_IP.setText(getIP()); 
     } 
    }); 
    btnRefresh.setBounds(212, 273, 89, 23); 
    contentPane.add(btnRefresh); 

    textField = new JTextField(); 
    textField.setText(Integer.toString(portNumber)); 
    textField.setColumns(10); 
    textField.setBounds(96, 305, 103, 20); 
    contentPane.add(textField); 

    lblPort = new JLabel("Port:"); 
    lblPort.setBounds(49, 308, 44, 14); 
    contentPane.add(lblPort); 

    JButton btnNewButton = new JButton("dc"); 
    btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      ss = null; 
     } 
    }); 
    btnNewButton.setBounds(10, 185, 51, 23); 
    contentPane.add(btnNewButton); 
} 

private String getIP() 
{ 
    URL site = null; 
    try { 
     site = new URL("http://checkip.amazonaws.com"); 
    } catch (MalformedURLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    BufferedReader reader = null; 
    try { 
     reader = new BufferedReader(new InputStreamReader(site.openStream())); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    try 
    { 
     return InetAddress.getLocalHost().getHostAddress().toString(); 
     //return reader.readLine(); 
    } 
    catch(Exception e) 
    { 

    } 

    return null; 
} 

}

ClientHandler.java:

package Server; 
import java.awt.HeadlessException; 
import java.io.BufferedReader; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.MalformedURLException; 
import java.net.Socket; 
import java.net.URL; 
import java.util.ArrayList; 

import javax.swing.JOptionPane; 


public class ClientHandler extends Thread{ 

private Socket clientSocket = null; 
private DataInputStream dis = null; 
private static ArrayList<Socket> users = null; 


private String getIP() 
{ 
    URL website = null; 
    try { 
     website = new URL("http://checkip.amazonaws.com"); 
    } catch (MalformedURLException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 

    BufferedReader reader = null; 
    try { 
     reader = new BufferedReader(new InputStreamReader(website.openStream())); 
    } catch (IOException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 

    try { 
     return reader.readLine(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    return null; 
} 


public ClientHandler(Socket clientSocket) 
{ 

    this.clientSocket = clientSocket; 

    if(users==null) 
     users = new ArrayList<Socket>(); 

    try 
    { 
     users.add(clientSocket); 
    } 
    catch(Exception ex) 
    { 
     System.out.println("Adding client's socket to socket list failed!"); 
    } 


    try 
    { 
     dis = new DataInputStream(clientSocket.getInputStream()); 
    } 
    catch(Exception e) 
    { 

    } 

    Server.addTextToServerLog("Trying to add a new client!"); 
    /* 
    try { 
     Thread.sleep(5000); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    */ 
    Server.addTextToServerLog("Client added!"); 
} 

public void tellEveryone(String message, String name) 
{ 
    for (Socket socket : users) { 
     Socket s = socket; 

     try { 
      DataOutputStream dos = new DataOutputStream(s.getOutputStream()); 
      dos.writeUTF(name + ":" + message); 

      dos.close(); 
     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
    } 
} 

public void disconnect() 
{ 

} 


// reciving messages from a specific client and send to everyone else 
public void run() 
{ 
    while(true) 
    { 
     String line = null; 

     try { 
      System.out.println("Reading client input"); 

      Server.addTextToServerLog("-line-"); 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      line = dis.readUTF(); 
      Server.addTextToServerLog("Line=" + line); 

      if(line!=null) 
      { 

       if(line.startsWith("/name ")) 
       { 
        String name = line.replaceFirst("/name", ""); 
        tellEveryone("joined room!", name); 
        Server.addTextToServerLog(name + "joined room!"); 
       } 
       else 
       { 
        tellEveryone(line, null); 
        Server.addTextToServerLog(line); 
       } 

      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
     } 

    } 
} 

}

Es wirft Ausnahme von zweiten Versuch: (Client.java - dies wird ausgeführt, wenn die Sendetaste gedrückt wird)

b_send.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      if(!connected) 
      { 
       JOptionPane.showMessageDialog(null, "You have to connect first!"); 
       return; 
      } 

      String message = tf_input.getText(); 

      try { 
       ta_chat.append("writing UTF" + '\n'); 
       dos.writeUTF(message); 
       ta_chat.append(ta_chat.getText().trim() + "writing UTF succeded" + '\n'); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       ta_chat.append(ta_chat.getText().trim() + "writing UTF failed" + '\n'); 
      } 

      tf_input.setText(null); 
     } 
    }); 

Server.java: (dieser Teil die relevant sein können ein)

while(true) 
    { 
     Socket s = null; 
     try { 
      s = ss.accept(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 

     } 

     System.out.println("Creating new ClientListener!"); 
     new ClientHandler(s).start(); 
    } 

ClientHandler.run():

public void run() 
{ 
    while(true) 
    { 
     String line = null; 

     try { 
      System.out.println("Reading client input"); 

      Server.addTextToServerLog("-line-"); 
      try { 
       //Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      line = dis.readUTF(); // <----------- this works only 1st time 
      Server.addTextToServerLog("Line=" + line); 

      if(line!=null) 
      { 

       if(line.startsWith("/name ")) 
       { 
        String name = line.replaceFirst("/name", ""); 
        tellEveryone("joined room!", name); 
        Server.addTextToServerLog(name + "joined room!"); 
       } 
       else 
       { 
        tellEveryone(line, null); 
        Server.addTextToServerLog(line); 
       } 

      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
     } 

    } 
} 

Ich muss sagen, dass die App vor einer Weile funktionierte, es gab Nebenläufigkeitsprobleme, aber es funktionierte gut genug. Ich habe keine Unterstützung.

+0

Veröffentlichen Sie die gesamte Ausnahme stacktrace –

Antwort

1

Mindestens ein Teil des Problems ist in tellEveryone(2) Methode Ihres Kunden:

DataOutputStream dos = new DataOutputStream(s.getOutputStream()); 
dos.writeUTF(name + ":" + message); 
dos.close(); 

Sie Schließen der Strom jedes Mal, wenn Sie eine Nachricht senden. Da dos mit dem Ausgabestream der Instanz Socket Ihres Clients erstellt wird, schließt es den Socket bei jedem Aufruf der close()-Methode unter dos. Sie sollten wahrscheinlich dos als eine Mitgliedsvariable Ihrer Clientklasse speichern und nur schließen, wenn Sie wirklich trennen möchten.

Darüber hinaus sollten Sie wahrscheinlich jedes Mal, wenn Sie eine Nachricht senden, dos.flush() anrufen, um sicherzustellen, dass die gesamte Nachricht in den Socket geschrieben wird. Manchmal werden OutputStream Implementierungen Daten zwischenspeichern, bis eine bestimmte Puffergröße erreicht ist, und dann den gesamten Puffer auf den zugrunde liegenden Datenstrom spülen (in diesem Fall ist der zugrunde liegende Datenstrom der Socket selbst). Wenn Sie nicht flush() aufrufen, besteht die Möglichkeit, dass ein Teil der Nachricht aufgrund von Pufferung nicht in den Socket geschrieben wird.

Vergewissern Sie sich im gesamten Code, dass Sie keine offenen Sockets schließen, es sei denn, Sie möchten die Verbindung wirklich trennen. Dadurch wird Ihr Problem wahrscheinlich behoben.

+0

Ja. Ich entfernte: – Radu

+0

Ich entfernte dos.close(). Jetzt empfängt Server Nachrichten. Aber manchmal erhalten Clients keine Eingaben vom Server zurück. Es scheint zufällig zu sein. – Radu

+0

Auch wenn dieser Client keine Nachrichten vom Server empfängt, kann er sie an den Server senden und sie an andere Clients (die funktionieren) wiedergeben. Wenn ein Client einmal keine Nachricht erhält, wird er dies nie tun. Ich meine einige Clients arbeiten, aber andere sind nicht in der Lage, Server-Ausgabe zu erhalten. – Radu