2015-05-23 3 views
1

Я пытаюсь закодировать чат-приложение с несколькими клиентами и одним сервером. Идея: клиент отправляет String на сервер, сервер работает с ним и возвращается к объекту клиента (только клиент, который отправляет строку, получает ответ!).Несколько «чатов» клиентов

Проблема: один клиент работает хорошо. Запуск второго клиента создает проблемы: клиент 2 получает ответ для клиента 1, и после первого ответа оба клиента ничего не могут отправить.

Другими словами, мне нужна помощь, пожалуйста.

Вот код: Сервер:

public class serverWindow extends JFrame { 

private JPanel contentPane; 
private static JTextField tfAddition; 
static JTextPane tp; 

// connection stuff 
static ServerSocket ss = null; 
static Socket soc = null; 
static DataInputStream din; 
static ObjectOutputStream obout; 
static int port = 1255; 

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

    try 
    { 
     ss = new ServerSocket(port);  
     while(true) 
     { 
      try 
      { 
       soc = ss.accept();    
       echoThread X = new echoThread(soc, tp); 
       X.start(); 
      } 
      catch(Exception ex) 
      { 
       ex.printStackTrace(); 
      } 
     } 
    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
    } 
    finally 
    { 
     ss.close(); 
    } 
} 

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

    JScrollPane scrollPane = new JScrollPane(); 
    scrollPane.setBounds(10, 11, 414, 183); 
    contentPane.add(scrollPane); 

    tp = new JTextPane(); 
    tp.setEditable(false); 
    scrollPane.setViewportView(tp); 
} 
} 

echoThread:

public class echoThread extends Thread 
{ 
protected Socket soc; 
public JTextPane tp; 
static DataInputStream din = null; 
static ObjectOutputStream obout = null; 

public echoThread(Socket soc, JTextPane tp) 
{ 
    this.soc = soc; 
    this.tp = tp; 
} 

public void run() 
{ 
    try 
    { 
     din = new DataInputStream(this.soc.getInputStream()); 
     obout = new ObjectOutputStream(soc.getOutputStream()); 

     while(true) 
     { 
      String message = din.readUTF();       
      tp.setText(tp.getText().trim() + "\n" + message); 
      Response res = new Response(message, message.length()); 
      obout.writeObject(res); 
      obout.flush(); 
     } 
    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
     return; 
    } 
    finally 
    { 
     try 
     { 
      soc.close(); 
      din.close(); 
      obout.close(); 
     } 
     catch(Exception ex) 
     { 
      ex.printStackTrace(); 
      return; 
     } 
    } 
} 
} 

клиент:

public class clientW extends JFrame { 

private JPanel contentPane; 
private JTextField textField; 
private static JTextPane textPane; 

// sockets 
static Socket soc = null; 
static ObjectInputStream obin = null; 
static DataOutputStream dout = null; 
static int port = 1255; 
static String host = "localhost"; 

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

    try 
    { 
     try 
     { 
      soc = new Socket(host, port); 
      dout = new DataOutputStream(soc.getOutputStream()); 
      obin = new ObjectInputStream(soc.getInputStream()); 
      while(true) 
      { 
       Response res = (Response) obin.readObject(); 
       textPane.setText(textPane.getText().trim() + "\n" + res.combineText()); 
      } 
     } 
     catch(Exception ex) 
     { 
      ex.printStackTrace(); 
     } 

    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
    }   
    finally 
    { 
     soc.close(); 
     obin.close(); 
     dout.close(); 
    } 
} 

public clientW() { 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 450, 300); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    setContentPane(contentPane); 
    contentPane.setLayout(null); 

    JButton btnNewButton = new JButton("send"); 
    btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) 
     { 
      try 
      { 
       dout.writeUTF(textField.getText().trim()); 
       dout.flush(); 
      } 
      catch(Exception ex) 
      { 
       ex.printStackTrace(); 
      } 
     } 
    }); 
    btnNewButton.setBounds(335, 227, 89, 23); 
    contentPane.add(btnNewButton); 

    textField = new JTextField(); 
    textField.setBounds(10, 227, 315, 21); 
    contentPane.add(textField); 
    textField.setColumns(10); 

    textPane = new JTextPane(); 
    textPane.setEditable(false); 
    textPane.setBounds(10, 11, 414, 205); 
    contentPane.add(textPane); 
} 
} 

ответ

1

гама и obout в вашем echoThread объявлены как статические переменные, так они распределяются между всеми клиентами. Это может быть исправлено путем объявления din и obout без ключевого слова static. Это исправить?

+0

Он делает. Благодарю. –

1

Вы определяете потоки в echoThread как статические, то есть все экземпляры этого класса будут обмениваться этими объектами. Из-за этого при запуске второго экземпляра echoThread он перезаписывает потоки первого экземпляра, так что потоки для одного сокета теряются. Если вы измените определение на:

private DataInputStream din = null; 
private ObjectOutputStream obout = null; 

похоже, что вы работали так, как описано.

Смежные вопросы