等到状态变为真

时间:2015-11-04 13:35:01

标签: java

我有三个类,分别是TCPClient.java,TCPProtocol.java,TCPServer.java。

*更新,我也粘贴了我的完整TCPServer.java

首先,用户将在TCPProtocol GUI窗口中输入文本(使用JTextarea),然后单击“发送”按钮。如果用户单击“发送”,TCPClient将从TCPProtocol获取输入,最后将发送到TCPServer。所以问题是,我的TCPClient永远不会从TCPProtocol获得输入。

TCPServer.java

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

public class TCPServer {

public static void main(String[] args) throws IOException {

    //TCP component
    ServerSocket serverSocket = null;
    Socket clientSocket = null;
    int port = 8081;
    TCPProtocol nis = new TCPProtocol();//create an object to call method in protocol class

    try {
        serverSocket = new ServerSocket(port);
        System.out.println("Waiting for connection...");
        System.out.println();
    } catch (IOException e) {
        System.out.println(e.toString() + " :Could not listen on port: " + port);
        System.exit(1);
    }

    try {
        clientSocket = serverSocket.accept();
        System.out.println("TCP Session established.");
        nis.frame.setVisible(true);
        nis.frame.setAlwaysOnTop(true);
        System.out.println();

    } catch (IOException e) {
        System.out.println(e.toString() + " :Accept failed.");
        System.exit(1);
    }

    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

    String inputLine, outputLine;
    outputLine = nis.processAnswer(null);//get Learn Learn English line
    out.println(outputLine);//and send the line out to client
    nis.Jservertxt.setText(outputLine);

    while ((inputLine = in.readLine()) != null) {
         outputLine = nis.processAnswer(inputLine);
         out.println(outputLine);
         nis.Jservertxt.setText(outputLine);
         if (outputLine.equalsIgnoreCase("Don't miss me! Bye Bye!"))
            break;
         else if (outputLine.equalsIgnoreCase("Thank For Your Guessing. Have a Nice Day =)"))
            break;
    }

    //End connection
    out.flush();
    out.close();
    in.close();
    nis.frame.setVisible(false);
    if (!clientSocket.isClosed())
        clientSocket.close();
        nis.frame.setVisible(false);
    if (!serverSocket.isClosed())
        serverSocket.close();
        nis.frame.setVisible(false);

    System.out.println("TCP session closed.");
}
}

这是我的TCPProtocol.java代码

public volatile boolean getPressed;
Jsend.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {

            String Data = Jusertxt.getText();
            Jusertxt.setText(null);
            System.out.println(Data);
            getPressed=true;
    }
    });
    }

    public boolean getPressed()
    {
        return getPressed;
    }

我不会在这里粘贴完整的代码,因为我只是显示出问题所在的部分。

这是我的TCPClient代码

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

public class TCPClient{

public static void main(String[] args)  throws IOException, InterruptedException{

    //TCP component
    int port = 8081;
    String host = "localhost";
    Socket nisSocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    TCPProtocol pro = new TCPProtocol();

    try {
        nisSocket = new Socket(host, port);
        out = new PrintWriter(nisSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(nisSocket.getInputStream()));
    } catch (UnknownHostException e) {
        System.out.println(e.toString() + " :Don't know about " + host);
        System.exit(1);
    } catch (IOException e) {
        System.out.println(e.toString() + " :Couldn't get I/O for the connection to " + host);
        System.exit(1);
    }

    BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
    String fromServer, fromUser;

    while ((fromServer = in.readLine()) != null) {
            System.out.println("Server: " + fromServer);
        if (fromServer.equalsIgnoreCase("Don't miss me! Bye Bye!"))
            break;
        if (fromServer.equalsIgnoreCase("Thank For Your Guessing. Have a Nice Day =)"))
            break;

        if (pro.getPressed())
        {
            fromUser = pro.Jusertxt.getText();
            if (fromUser != null) {
                    System.out.println("\nClient: " + fromUser);
                    out.println(fromUser);
                    }
        }
            System.out.println("fail liao");

    }
    System.out.println("try again");
    //End connection
    out.flush();
    out.close();        
    in.close(); 
    stdIn.close();

    //if (!nisSocket.isClosed())
        nisSocket.close();
    System.out.println("TCP session closed.");
}
}

那么,如果只有getPressed()方法为真,我怎么才能让TCPClient.java进程。

我尝试使用volatile布尔变量但不能正常工作。或者我应该使用synchronized?

更改后解决从服务器到客户端调用GUI代码

while ((fromServer = in.readLine()) != null) {
            System.out.println("Server: " + fromServer);
        if (fromServer.equalsIgnoreCase("Don't miss me! Bye Bye!"))
            break;
        if (fromServer.equalsIgnoreCase("Thank For Your Guessing. Have a Nice Day =)"))
            break;

        pro.frame.setVisible(true);
        pro.frame.setAlwaysOnTop(true);
        pro.Jservertxt.setText(fromServer);
        if(pro.getPressed()){
            fromUser = pro.getMessage();
                if (fromUser != null) {
                        System.out.println("\nClient: " + fromUser);
                        out.println(fromUser);
                }
        }
    }

2 个答案:

答案 0 :(得分:1)

这是一个主线程的一个小例子(将其视为您的TCPClient),等待用户点击按钮(将此部分视为您的TCPProtocol):

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Test extends JFrame {

    public Object       lock    = new Object();
    private JTextArea   area    = new JTextArea();

    public Test() {
        super("test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton send = new JButton("send");
        send.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                synchronized (lock) {
                    lock.notify();
                }

            }
        });
        add(area);
        add(send, BorderLayout.SOUTH);
    }

    public String pullText() {
        String result = area.getText();
        area.setText("");
        return result;

    }

    public static void main(String[] args) {
        Test t = new Test();
        t.setSize(200, 200);
        t.setVisible(true);

        while (true) {
            synchronized (t.lock) {
                try {
                    t.lock.wait();
                    System.out.println(t.pullText());
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }

    }

}

也许您可以对您的系统应用类似的方法。

警告:这只是一个快速而肮脏的例子,请您仔细检查。通常,在处理同步时应该非常小心。

编辑: 作为起点,您可以修改TCPProtocol类(您发布的部分),如下所示:

public volatile boolean getPressed;

private Object lock = new Object(); // added lock for wait/notify coordination
private String Data; //changed scope to make it accessible in getMessage()

Jsend.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {

        synchronized(lock){
            Data = Jusertxt.getText(); // no more a local variable, it's an instance attribute now, see declaration above
            Jusertxt.setText(null);
            System.out.println(Data);
            getPressed=true;
            lock.notify(); // notify client that user performed action
        }
    });
}

public boolean getPressed(){
    synchronized (lock) {
        try {
            lock.wait(); // wait for user to perform action...
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    return getPressed; // ...then return value (I guess getPressed will always be true at this point)
}

public String getMessage(){ // call this in TCPClient instead of pro.Jusertxt.getText()
    return Data;
}

我添加了一个锁定对象来启用wait / notify机制并将其应用于actionPerformed和getPressed方法。 我还改变了Data变量的范围,并添加了一个公共方法来获取它的值(getMessage())。如果你仔细检查你的代码,你会发现你总是从TCPClient.java中的pro.Jusertxt.getText()得到null,因为你在actionPerformed中将它设置为null。因此,在TCPClient.java中将pro.Jusertxt.getText()更改为pro.getMessage()。

// [...]
fromUser = pro.getMessage(); // used to be fromUser = pro.Jusertxt.getText();
// [...]

如果你使这个原始版本工作,那么你可以改进和重构它,使它更干净和一致。 (例如,我怀疑你实际上并不需要getPressed变量,因为它实际上总是如此)

我承认我没有测试过这段代码,所以你可能需要稍微修改或调整一下,但我希望它能说明我的意思是你可以应用我发布到你系统的代码。

希望它有所帮助。

祝你好运: - )

答案 1 :(得分:0)

你可以试试这个:

while (!pro.getPressed()) {
                    System.out.println("still not true");
                    Thread.sleep(1000);
                }
System.out.println("getPressed is true");