簡體   English   中英

單服務器和多客戶端中的通信死鎖

[英]Communication deadlock in single server and multiple clients

我是Java初學者,正在為聊天服務器應用程序編程。 該應用程序可促進n個客戶之間的聊天

當前問題
在我的代碼中, Chatinterface class下面是客戶端類。 打開2個Chatinterface類的實例后,當我嘗試通過在文本區域中輸入消息進行通信時。 我沒有在另一個客戶端實例窗口中收到消息,反之亦然。 我的套接字無法通信或存在其他問題。

預期產量

客戶端和客戶端都必須進行通信,並且消息必須顯示在相應的窗口中。

任何人都可以告訴我發生了什么問題以及在哪里可以更正我的代碼?

無論如何,我都同時粘貼了客戶端代碼和服務器代碼以進行詳細分析。

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

    }

}

您的代碼很難閱讀和理解。 嘗試使用相關的變量名。 嘗試着重於與問題相關的代碼。

我不知道您的問題是什么,但是我確定這里有問題:

e.getActionCommand() == "s"

和這里

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

這些都不是正確的(它測試指針是否相等,而不是內容)( 在此處了解更多信息 )。

所以寫這個:

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

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

對於任何其他問題:

  • 使用調試器
  • 使用日志

正如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嗅探通信。

這里沒有僵局。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM