多个客户"聊天"

时间:2015-05-23 22:31:03

标签: java

我尝试使用多个客户端和单个服务器编写类似聊天的应用程序。想法:客户端将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);
}
}

2 个答案:

答案 0 :(得分:1)

echoThread中的

din和obout被声明为静态变量,因此它们在所有客户端之间共享。这可以通过在没有关键字static的情况下声明din和obout来纠正。这样可以解决吗?

答案 1 :(得分:1)

您将echoThread中的流定义为静态,这意味着该类的所有实例都将共享这些对象。因此,当第二个echoThread实例启动时,它会覆盖第一个实例的流,因此一个套接字的流将丢失。如果将定义更改为:

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

它似乎按照你描述的那样工作。