单个服务器和多个客户端中的通信死锁

时间:2014-08-02 10:11:03

标签: java sockets network-programming

我是Java初学者并编写聊天服务器应用程序。该应用程序促进了n个客户之间的聊天

当前问题
在下面的代码中,Chatinterface class是客户端类。在我打开Chatinterface类的2个实例后,当我尝试通过在文本区域中输入消息进行通信时。我没有在另一个客户端实例窗口中收到消息,反之亦然。我的套接字没有通信或存在其他问题。

预期产出

两个客户端都必须进行通信,并且必须在相应的窗口中显示消息。

任何人都可以告诉我发生了什么问题,我在哪里可以更正我的代码?

无论如何,我会粘贴我的客户端和服务器代码进行详细分析。

package stack;

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
class Chatinterface implements ActionListener {
    private JFrame frame;
    JTextArea textArea_1;
    JTextArea textArea_2;
    JButton btnNewButton;
    JButton btnNewButton_1;
    Socket client;
    BufferedReader read;
    PrintWriter write;
    String getmsg;
    String gettext;
    public Chatinterface(){
        communicate();
        displaygui();
    }
    private void communicate() {
        // TODO Auto-generated method stub
        try {
            client = new Socket("localhost",3420);
            read = new BufferedReader(new InputStreamReader(client.getInputStream()));
            write = new PrintWriter(client.getOutputStream(),true);
            if(getmsg!=null)
            {
                while(true)
                {
                    textArea_2.setText(getmsg);
                }
            }

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void displaygui() {
        frame = new JFrame();
        frame.setResizable(false);
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        SpringLayout springLayout = new SpringLayout();
        frame.getContentPane().setLayout(springLayout);
        textArea_1 = new JTextArea();
        springLayout.putConstraint(SpringLayout.NORTH, textArea_1, 171, SpringLayout.NORTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.WEST, textArea_1, 10, SpringLayout.WEST, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.SOUTH, textArea_1, -10, SpringLayout.SOUTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.EAST, textArea_1, 340, SpringLayout.WEST, frame.getContentPane());
        frame.getContentPane().add(textArea_1);
        textArea_2 = new JTextArea();
        textArea_2.setWrapStyleWord(true);
        textArea_2.setEditable(false);
        springLayout.putConstraint(SpringLayout.NORTH, textArea_2, 10, SpringLayout.NORTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.WEST, textArea_2, 0, SpringLayout.WEST, textArea_1);
        springLayout.putConstraint(SpringLayout.SOUTH, textArea_2, 160, SpringLayout.NORTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.EAST, textArea_2, 0, SpringLayout.EAST, textArea_1);
        frame.getContentPane().add(textArea_2);
        btnNewButton = new JButton("Send");
        springLayout.putConstraint(SpringLayout.NORTH, btnNewButton, -76, SpringLayout.SOUTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.WEST, btnNewButton, 5, SpringLayout.EAST, textArea_1);
        springLayout.putConstraint(SpringLayout.SOUTH, btnNewButton, -27, SpringLayout.SOUTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.EAST, btnNewButton, 82, SpringLayout.EAST, textArea_1);
        frame.getContentPane().add(btnNewButton);
        btnNewButton.addActionListener(this);
        btnNewButton.setActionCommand("S");
        btnNewButton_1 = new JButton("Logout");
        springLayout.putConstraint(SpringLayout.NORTH, btnNewButton_1, 50, SpringLayout.NORTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.WEST, btnNewButton_1, -65, SpringLayout.EAST, btnNewButton);
        springLayout.putConstraint(SpringLayout.SOUTH, btnNewButton_1, 108, SpringLayout.NORTH, frame.getContentPane());
        springLayout.putConstraint(SpringLayout.EAST, btnNewButton_1, 0, SpringLayout.EAST, btnNewButton);
        frame.getContentPane().add(btnNewButton_1);
        btnNewButton_1.addActionListener(this);
        btnNewButton_1.setActionCommand("L");
        frame.setVisible(true);
    }
    public static void main(String args[])
    {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new Chatinterface();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {

        if(arg0.getActionCommand().equals("S"))
        {   
            String gettext2;
            gettext2 = textArea_1.getText();
            textArea_2.append(gettext2);
            textArea_1.setText("");
            write.println(gettext2);
        }

        if(arg0.getActionCommand().equals("L")){
            try {
                read.close();
                write.close();
                client.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

以下是服务器类的代码

package stack;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
public class Server1  {
    public static void main(String[] args) throws Exception {
        Socket s;
        ServerSocket server = new ServerSocket(3420);
        while(true)
        {
            s = server.accept();
            Handler handler1 = new Handler(s);
            Thread t1 = new Thread(handler1);
            t1.start();


        }
    }
}

这是处理程序类

package stack;

import java.io.*;
import java.net.*;

public class Handler implements Runnable {

    Socket s;

    String getmsg = null;
    String sendmsg;

    public Handler(Socket s) {
        this.s = s;

    }

    public void run() {

        try {
            BufferedReader reader1;
            PrintWriter writer1;
            reader1 = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));
            writer1 = new PrintWriter(s.getOutputStream(), true);
            sendmsg = reader1.readLine();

            while (true) {
                if (reader1 == null) {

                    s.close();
                } else {
                    writer1.println(sendmsg);
                }
            }

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

    }

}

2 个答案:

答案 0 :(得分:2)

您的代码阅读和理解起来很复杂。尝试使用相关的变量名称。尽量关注与问题相关的代码。

我不知道你的问题是什么,但我确定这里有问题:

e.getActionCommand() == "s"

在这里

if (e.getActionCommand() == "L")

这些都不是真的(它测试指针相等,而不是内容)(阅读更多here)。

所以写下来:

e.getActionCommand().equals("s")

if (e.getActionCommand().equals("L"))

对于任何进一步的问题:

  • 使用调试器
  • 使用日志

答案 1 :(得分:0)

正如ben75所说,代码很难阅读并且有一些错误。让我提供一些建议,以便能够帮助您:

1 - 不要在构造函数中创建功能。这就是你在Chatinterface中所做的。构造函数应该只创建对象。然后你可以添加一个名为" execute"做这项工作。

private void execute()
{
    ...
}

2 - 我还没有测试过通信部分,但它应该在客户端和服务器之间进行通信。我运行Chatinterface,代码正确到达这一行:

write.println(gettext2);

3 - 您没有看到该消息的错误是因为,在构造函数中,它正在调用communication和displaygui。通信中的代码应该显示从服务器接收的消息:

        if(getmsg!=null)
        {
            while(true)
            {
                textArea_2.setText(getmsg);
            }
        }

但是这段代码只在开头执行一次,getmsg为null,执行控制永远不会再回到这段代码。 我假设您正在尝试在客户端中创建一个不同的线程来执行此代码并进入无限循环。

如果您对通信客户端服务器有疑问,可以使用Wireshark或tcpdump来嗅探通信。

这里没有死锁。