我正在创建一个简单的 Knock Knock 应用程序(套接字编程),其中有一个本地主机服务器和一个客户端。程序很简单,服务器会讲敲门笑话,这就是它应该如何进行,
Server: Knock Knock
Client: Who's there?
Server: Turnip.
Client: Turnip Who?
Server: Turnip the heat.
这就是程序应该如何进行的。但问题是我的 GUI 没有显示任何消息。在我的文本区域。这是我的代码。
服务器:
import java.net.*;
import java.io.*;
public class KnockKnockServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
KnockKnock 协议(protocol)
import java.net.*;
import java.io.*;
public class KnockKnockProtocol {
private static final int WAITING = 0;
private static final int SENTKNOCKKNOCK = 1;
private static final int SENTCLUE = 2;
private static final int ANOTHER = 3;
private static final int NUMJOKES = 5;
private int state = WAITING;
private int currentJoke = 0;
private String[] clues = { "Turnip", "Little Old Lady", "Atch", "Who", "Who" };
private String[] answers = { "Turnip the heat, it's cold in here!",
"I didn't know you could yodel!",
"Bless you!",
"Is there an owl in here?",
"Is there an echo in here?" };
public String processInput(String theInput) {
String theOutput = null;
if (state == WAITING) {
theOutput = "Knock! Knock!";
state = SENTKNOCKKNOCK;
} else if (state == SENTKNOCKKNOCK) {
if (theInput.equalsIgnoreCase("Who's there?")) {
theOutput = clues[currentJoke];
state = SENTCLUE;
} else {
theOutput = "You're supposed to say \"Who's there?\"! " +
"Try again. Knock! Knock!";
}
} else if (state == SENTCLUE) {
if (theInput.equalsIgnoreCase(clues[currentJoke] + " who?")) {
theOutput = answers[currentJoke] + " Want another? (y/n)";
state = ANOTHER;
} else {
theOutput = "You're supposed to say \"" +
clues[currentJoke] +
" who?\"" +
"! Try again. Knock! Knock!";
state = SENTKNOCKKNOCK;
}
} else if (state == ANOTHER) {
if (theInput.equalsIgnoreCase("y")) {
theOutput = "Knock! Knock!";
if (currentJoke == (NUMJOKES - 1))
currentJoke = 0;
else
currentJoke++;
state = SENTKNOCKKNOCK;
} else {
theOutput = "Bye.";
state = WAITING;
}
}
return theOutput;
}
}
客户。
import java.io.*;
import java.net.*;
public class KnockKnockClient {
public String fromServer;
public String fromUser;
public void Client() throws IOException {
Socket kkSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
kkSocket = new Socket("127.0.0.1", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: 127.0.0.1");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: 127.0.0.1");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("Bye."))
break;
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
out.close();
in.close();
stdIn.close();
kkSocket.close();
}
}
和用户界面
import java.awt.event.ActionListener;
public class KnockKnockWindow extends JFrame {
JTextArea clientTextArea;
JTextArea serverTextArea;
JButton submitButton;
public KnockKnockWindow() {
super("Chat Window");
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setSize(420,228);
getContentPane().setLayout(null);
clientTextArea = new JTextArea();
clientTextArea.setBounds(10, 118, 278, 51);
getContentPane().add(clientTextArea);
serverTextArea = new JTextArea();
serverTextArea.setBounds(10, 11, 278, 96);
getContentPane().add(serverTextArea);
submitButton = new JButton("Submit");
submitButton.setBounds(298, 118, 89, 51);
getContentPane().add(submitButton);
}
public void setServerText(String fromServer){
serverTextArea.setText(fromServer);
}
public void setClientText(String fromClient){
clientTextArea.setText(fromClient);
}
public String returnClientText(){
return clientTextArea.getText();
}
public void addSubmitListener(ActionListener sub){
submitButton.addActionListener(sub);
}
}
The Controller
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class KnockKnockController {
private KnockKnockClient client;
private KnockKnockWindow window;
public KnockKnockController(KnockKnockClient client, KnockKnockWindow window){
this.client = client;
this.window = window;
window.addSubmitListener(new SubmitListener());
window.setServerText(client.fromServer);
}
public class SubmitListener implements ActionListener{
public void actionPerformed(ActionEvent arg0) {
client.fromUser = window.returnClientText();
}
}
}
以及主要应用
import javax.swing.JFrame;
public class KnockTest extends JFrame{
public static void main (String[] args){
KnockKnockClient kkcl = new KnockKnockClient();
KnockKnockWindow kkw = new KnockKnockWindow();
KnockKnockController kkc = new KnockKnockController(kkcl,kkw);
}
}
我们将首先运行服务器,然后是主程序。
但是为什么我没有收到服务器发送的任何消息?当我点击开始时。服务器的文本区域应该显示 KnockKnock。但它似乎没有显示,有什么想法吗?抱歉,代码很长,但我不知道在这里缩短它们。因为我知道其中大多数都很重要
最佳答案
正如您所说,while 循环只是获取文本并将其打印到控制台,您到底在哪里打印到文本区域。
// Put this code somewhere in the Client class so that when it receives something,
// it can be added to the `JTextArea`
while ((fromServer = in.readLine()) != null)
{
// You seems like missed the part that sends it to the textArea
System.out.println("Server: " + fromServer);
// Here send the received thing to your textarea, which goes something like this
String str = "Server : " + fromServer + "\n";
tarea.append(str);
if (fromServer.equals("Bye."))
break;
// You can remove this part and put it inside the textField's actionPerformed method.
fromUser = stdIn.readLine();
if (fromUser != null)
{
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
全新编辑:
只需从命令提示符启动 KnockKnockServer,而不是从扩展 JFrame 的类启动。只需简单地编写 java KnockKnockServer,即可在命令提示符下运行您的服务器,现在在新的命令提示符下编译我给您的这个类并像 java KnockKnockClient 一样运行它,您会发现它并没有完全工作。
import java.awt.BorderLayout;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class KnockKnockClient extends JFrame
{
public String fromServer;
public String fromUser;
// Added by me.--------------------
private JTextArea tarea;
private JTextField tfield;
private JScrollPane spane;
private PrintWriter out = null;
/*------------------------------------*/
public void Client() throws IOException
{
Socket kkSocket = null;
//PrintWriter out = null; Shifted this to the instance variable
BufferedReader in = null;
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
try {
kkSocket = new Socket("127.0.0.1", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: 127.0.0.1");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: 127.0.0.1");
System.exit(1);
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
JPanel contentPane = new JPanel();
tarea = new JTextArea(10, 10);
spane = new JScrollPane(tarea);
tarea.setLineWrap(true);
tfield = new JTextField(10);
tfield.requestFocusInWindow();
contentPane.setLayout(new BorderLayout());
contentPane.add(spane, BorderLayout.CENTER);
contentPane.add(tfield, BorderLayout.PAGE_END);
setContentPane(contentPane);
pack();
setVisible(true);
Thread receiveMessage = new Thread(new ReceiveChat(in, stdIn, out));
receiveMessage.start();
tfield.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
// Here you will send it to the server side too, put that code here
fromUser = tfield.getText() + "\n";
if (fromUser != null)
{
System.out.println("Client: " + fromUser);
tarea.append(fromUser);
out.println(fromUser);
tfield.setText("");
}
}
});
//out.close();
//in.close();
//stdIn.close();
//kkSocket.close();
}
private class ReceiveChat implements Runnable
{
private BufferedReader in;
private BufferedReader stdIn;
private PrintWriter out;
public ReceiveChat(BufferedReader in, BufferedReader stdIn, PrintWriter out)
{
this.in = in;
this.stdIn = stdIn;
this.out = out;
}
public void run()
{
try
{
while ((fromServer = in.readLine()) != null) {
//System.out.println("Server: " + fromServer);
String str = "Server : " + fromServer + "\n";
tarea.append(str);
tarea.setCaretPosition(tarea.getDocument().getLength());
if (fromServer.equals("Bye."))
break;
/*Commented out by me.*/
/*fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
} */
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
KnockKnockClient client = new KnockKnockClient();
try
{
client.Client();
}
catch(Exception e)
{
e.printStackTrace();
}
}
});
}
}
只需让 KnockKnockServer 类的 while 循环如下所示:
while ((inputLine = in.readLine()) != null)
{
if (inputLine.length() > 0)
{
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
}
这将使其按预期工作。
关于java - Knock Knock 带有服务器和 UI 的应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9240308/