在小型聊天客户端中通过静态引用成员发送类实例
我正在用 Java 构建一个小型聊天室应用程序。 我在这里尝试做的是通过静态 ClientGUI 引用成员发送当前类 ClientGUI 实例(this)。 ServerApplication 类应该通过常规静态 getter(在 ServerApplication.main 中完成)接收当前的 clientGUI 引用。
经过一番繁琐的调试后,我仍然无法弄清楚为什么服务器端引用在收到 ClientGUI 引用后仍然为空( getCurrentClientGuiReference() 失败)。
(当然 - 发送的引用在传输到服务器端之前已初始化)。
是否无法通过本地静态引用成员传输当前引用? 也许我错过了什么?
下面是相关代码。
提前致谢。
客户端:
package chatApplication;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.swing.*;
public class ClientGUI implements StringConsumer, StringProducer
{
//Graphic components
private JFrame frame;
private JButton btConnect,btSend;
private JTextField tfText, tfServerName, tfPort, tfNickName;
private JPanel north,south,center;
ActionListener listener;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
JLabel mainLable = new JLabel();
//Utilities and connection components
private ConnectionProxy consumer = null;
private ConnectionProxy producer = null;
private ClientDescriptor clientDescriptor = null;
//Connection creation switch
private boolean isConnection = false;
//Client details meant for ClientDescriptor
static private String nickname = "Noname";
static private String serverAddress = "127.0.0.1";
static private String port = "1300";
static private ClientGUI currentClientGuiReference = null;
public ClientGUI()
{
frame = new JFrame("Chit & Chat");
listener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == btConnect)
{
if (isConnection == false)
{
ClientGUI.nickname = tfNickName.getText();
ClientGUI.serverAddress = tfServerName.getText();
ClientGUI.port = tfPort.getText();
ClientGUI.currentClientGuiReference = ClientGUI.this;
clientDescriptor = new ClientDescriptor(nickname, serverAddress, port, currentClientGuiReference); // Identical though NOT related to serverapplication's clientdescriptor
consumer = new ConnectionProxy(clientDescriptor, ClientGUI.this);
//Connecting client consumer as a producer
ClientGUI.this.addConsumer(consumer);
//Temporary text
mainLable.setText("Client consumer/producer thread is connected and running!");
}
}
if (event.getSource() == btSend)
{
String outGoingMessageToChat = tfText.getText();
producer.consume(outGoingMessageToChat); //sending outgoing msg to prducer.consume --> writeutf
}
}
};
btConnect = new JButton ("Connect to chat");
btSend = new JButton ("Send Message");
btConnect.addActionListener(listener);
btSend.addActionListener(listener);
tfText = new JTextField(50);
tfPort = new JTextField(10);
tfServerName = new JTextField(20);
tfNickName = new JTextField(10);
tfServerName.setText("127.0.0.1");
tfPort.setText("1300");
tfNickName.setText("Nickname");
north = new JPanel();
south = new JPanel();
center = new JPanel();
north.setBackground(Color.blue);
south.setBackground(Color.gray);
center.setBackground(Color.white);
south.add(tfText);
south.add(btSend);
north.add(tfNickName,BorderLayout.WEST);
north.add(tfServerName);
north.add(tfPort);
north.add(btConnect,BorderLayout.WEST);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing (WindowEvent event)
{
ClientGUI.this.removeConsumer(clientDescriptor);
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
}
);
frame.add(north,BorderLayout.NORTH);
frame.add(center,BorderLayout.CENTER);
frame.add(south,BorderLayout.SOUTH);
}
public void go()
{
ClientGUI.currentClientGuiReference = ClientGUI.this;
frame.setSize(700,700);
frame.setVisible(true);
mainLable.setText("Hey! " +
"Please enter a nickname, Server Address and a port in the text fields above" +
" and press 'Connect to chat'");
center.add(mainLable);
frame.add(center, BorderLayout.WEST);
if (isConnection == true)
{
mainLable.setText("Your details were sent.");
}
}
@Override
public void addConsumer(StringConsumer consumer)
{
this.producer = (ConnectionProxy)consumer;
//All actions completed - client thread producer/consumer is running.
isConnection = true;
}
@Override
public void removeConsumer(StringConsumer sc)
{
consumer.removeConsumer(clientDescriptor);
}
@Override
public void consume(String inComingMessageFromChat)
{
//Temporary code
mainLable.setText(inComingMessageFromChat);
}
public ConnectionProxy getConsumer()
{
return consumer;
}
public void setConsumer(ConnectionProxy consumer)
{
this.consumer = consumer;
}
/**
* @param args
*/
public static void main(String[] args)
{
ClientGUI clientGUI = new ClientGUI();
clientGUI.go();
}
public static String getNickname() {return nickname;}
public static String getServerAddress() {return serverAddress;}
public static String getPort() {return port;}
public static ClientGUI getCurrentClientGuiReference() {return currentClientGuiReference;}
}
服务器端:
package chatApplication;
import java.net.*;
import java.io.*;
public class ServerApplication {
public static int port = 1300;
public static int backlog = 5;
/**
* @param args
*/
public static void main(String[] args)
{
//Server side network variables
ServerSocket serverSocket = null;
//MessageBoard object
MessageBoard messageBoard = new MessageBoard();
//Client side network variables
Socket clientSocket = null;
ClientDescriptor clientDescriptor = null;
ConnectionProxy clientConnectionProxy = null;
//Client details meant for ClientDescriptor
String clientNickname = "Noname";
String clientServerAddress = "127.0.0.1";
String clientPort = "1300";
ClientGUI clientCurrentGuiReference = null;
try //Creating Server
{
serverSocket = new ServerSocket(port,backlog); //ServerSocket(int port, int backlog)
}
catch(IOException e)
{
e.printStackTrace();
}
while (true)
{
try
{
System.out.println("Server is waiting for Client requests...");
clientSocket = serverSocket.accept(); // A new thread is created for the new client
System.out.println("Client connection request accepted, creating client connection proxy...");
clientConnectionProxy = new ConnectionProxy(clientSocket); //connecting client socket to server
clientConnectionProxy.addConsumer(messageBoard); //Applying specific server system network utilities and connecting proxy to the messageboard
System.out.println("Requesting Client details from Client side...");
clientNickname = ClientGUI.getNickname();
clientServerAddress = ClientGUI.getServerAddress();
clientPort = ClientGUI.getPort();
clientCurrentGuiReference = ClientGUI.getCurrentClientGuiReference();
System.out.println("Creating Client Descriptor...");
clientDescriptor = new ClientDescriptor(clientNickname, clientServerAddress, clientPort, clientCurrentGuiReference);
clientDescriptor.addConsumer(messageBoard);
messageBoard.addConsumer(clientDescriptor);
clientConnectionProxy.start();//Start client connection's thread running
System.out.println("Client thread started...");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
I am building a small chat-room app in Java.
What I am trying to do here is to send the current class ClientGUI instance (this) through a static ClientGUI reference member. The ServerApplication class is supposed to receive this current clientGUI reference through a regular static getter (done in ServerApplication.main).
After some tiresome debugging I still can't figure out how come the Server side reference remains null after receiving the ClientGUI ref (The getCurrentClientGuiReference() fails).
(Of course - the sent ref is initialized before it is being transferred to server side).
Is it not possible to transfer the current ref through a local static ref member?
Perhaps I missed a something?
Bellow is the relevant code.
Thanks in advance.
Client side:
package chatApplication;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.swing.*;
public class ClientGUI implements StringConsumer, StringProducer
{
//Graphic components
private JFrame frame;
private JButton btConnect,btSend;
private JTextField tfText, tfServerName, tfPort, tfNickName;
private JPanel north,south,center;
ActionListener listener;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
JLabel mainLable = new JLabel();
//Utilities and connection components
private ConnectionProxy consumer = null;
private ConnectionProxy producer = null;
private ClientDescriptor clientDescriptor = null;
//Connection creation switch
private boolean isConnection = false;
//Client details meant for ClientDescriptor
static private String nickname = "Noname";
static private String serverAddress = "127.0.0.1";
static private String port = "1300";
static private ClientGUI currentClientGuiReference = null;
public ClientGUI()
{
frame = new JFrame("Chit & Chat");
listener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == btConnect)
{
if (isConnection == false)
{
ClientGUI.nickname = tfNickName.getText();
ClientGUI.serverAddress = tfServerName.getText();
ClientGUI.port = tfPort.getText();
ClientGUI.currentClientGuiReference = ClientGUI.this;
clientDescriptor = new ClientDescriptor(nickname, serverAddress, port, currentClientGuiReference); // Identical though NOT related to serverapplication's clientdescriptor
consumer = new ConnectionProxy(clientDescriptor, ClientGUI.this);
//Connecting client consumer as a producer
ClientGUI.this.addConsumer(consumer);
//Temporary text
mainLable.setText("Client consumer/producer thread is connected and running!");
}
}
if (event.getSource() == btSend)
{
String outGoingMessageToChat = tfText.getText();
producer.consume(outGoingMessageToChat); //sending outgoing msg to prducer.consume --> writeutf
}
}
};
btConnect = new JButton ("Connect to chat");
btSend = new JButton ("Send Message");
btConnect.addActionListener(listener);
btSend.addActionListener(listener);
tfText = new JTextField(50);
tfPort = new JTextField(10);
tfServerName = new JTextField(20);
tfNickName = new JTextField(10);
tfServerName.setText("127.0.0.1");
tfPort.setText("1300");
tfNickName.setText("Nickname");
north = new JPanel();
south = new JPanel();
center = new JPanel();
north.setBackground(Color.blue);
south.setBackground(Color.gray);
center.setBackground(Color.white);
south.add(tfText);
south.add(btSend);
north.add(tfNickName,BorderLayout.WEST);
north.add(tfServerName);
north.add(tfPort);
north.add(btConnect,BorderLayout.WEST);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing (WindowEvent event)
{
ClientGUI.this.removeConsumer(clientDescriptor);
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
}
);
frame.add(north,BorderLayout.NORTH);
frame.add(center,BorderLayout.CENTER);
frame.add(south,BorderLayout.SOUTH);
}
public void go()
{
ClientGUI.currentClientGuiReference = ClientGUI.this;
frame.setSize(700,700);
frame.setVisible(true);
mainLable.setText("Hey! " +
"Please enter a nickname, Server Address and a port in the text fields above" +
" and press 'Connect to chat'");
center.add(mainLable);
frame.add(center, BorderLayout.WEST);
if (isConnection == true)
{
mainLable.setText("Your details were sent.");
}
}
@Override
public void addConsumer(StringConsumer consumer)
{
this.producer = (ConnectionProxy)consumer;
//All actions completed - client thread producer/consumer is running.
isConnection = true;
}
@Override
public void removeConsumer(StringConsumer sc)
{
consumer.removeConsumer(clientDescriptor);
}
@Override
public void consume(String inComingMessageFromChat)
{
//Temporary code
mainLable.setText(inComingMessageFromChat);
}
public ConnectionProxy getConsumer()
{
return consumer;
}
public void setConsumer(ConnectionProxy consumer)
{
this.consumer = consumer;
}
/**
* @param args
*/
public static void main(String[] args)
{
ClientGUI clientGUI = new ClientGUI();
clientGUI.go();
}
public static String getNickname() {return nickname;}
public static String getServerAddress() {return serverAddress;}
public static String getPort() {return port;}
public static ClientGUI getCurrentClientGuiReference() {return currentClientGuiReference;}
}
Server side:
package chatApplication;
import java.net.*;
import java.io.*;
public class ServerApplication {
public static int port = 1300;
public static int backlog = 5;
/**
* @param args
*/
public static void main(String[] args)
{
//Server side network variables
ServerSocket serverSocket = null;
//MessageBoard object
MessageBoard messageBoard = new MessageBoard();
//Client side network variables
Socket clientSocket = null;
ClientDescriptor clientDescriptor = null;
ConnectionProxy clientConnectionProxy = null;
//Client details meant for ClientDescriptor
String clientNickname = "Noname";
String clientServerAddress = "127.0.0.1";
String clientPort = "1300";
ClientGUI clientCurrentGuiReference = null;
try //Creating Server
{
serverSocket = new ServerSocket(port,backlog); //ServerSocket(int port, int backlog)
}
catch(IOException e)
{
e.printStackTrace();
}
while (true)
{
try
{
System.out.println("Server is waiting for Client requests...");
clientSocket = serverSocket.accept(); // A new thread is created for the new client
System.out.println("Client connection request accepted, creating client connection proxy...");
clientConnectionProxy = new ConnectionProxy(clientSocket); //connecting client socket to server
clientConnectionProxy.addConsumer(messageBoard); //Applying specific server system network utilities and connecting proxy to the messageboard
System.out.println("Requesting Client details from Client side...");
clientNickname = ClientGUI.getNickname();
clientServerAddress = ClientGUI.getServerAddress();
clientPort = ClientGUI.getPort();
clientCurrentGuiReference = ClientGUI.getCurrentClientGuiReference();
System.out.println("Creating Client Descriptor...");
clientDescriptor = new ClientDescriptor(clientNickname, clientServerAddress, clientPort, clientCurrentGuiReference);
clientDescriptor.addConsumer(messageBoard);
messageBoard.addConsumer(clientDescriptor);
clientConnectionProxy.start();//Start client connection's thread running
System.out.println("Client thread started...");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为 static 不会做你认为它会做的事情。如果客户端和服务器分别运行(如在两个不同的进程和两个不同的 JVM 中),那么将任何变量分配给任何东西都不会使相同的值/对象对客户端和服务器都可见。您必须使用某种方式在进程之间进行通信。
一旦您设法将 ClientGUI 连接到服务器,我怀疑您是否能够按照您想要的方式使用它。 ClientGUI也只是一个对象,无法在客户端和服务器之间进行通信。您也必须自己处理。
I think static doesn't do what you think it does. If Client and Server are running separately--as in two different processes and two different JVMs--then no amount of assigning any variable to anything will make the same value/object visible to both Client and Server. You'll have to use some way of communicating between the processes.
Once you manage to get a ClientGUI to the Server, I doubt you'll be able to use it the way you want. The ClientGUI is also just an object with no ability to communicate between the Client and Server. You'll have to manage that yourself, too.
据我所知,服务器和客户端处于不同的进程中。它们是完全独立的 - 在客户端进程中设置静态变量不会更改服务器进程中的相同静态变量。
The server and client are in different processes, as far as I can see. They're completely separate - setting a static variable in the client process won't change the same static variable in the server process.
我能想到的唯一方法可能适合您想要做的事情是使用序列化,它可用于将对象表示为字节序列,然后可以使用 ObjectOutputStream 发送并根据需要使用 ObjectInputStream 接收在发送/接收对象中。
虽然我曾经做过类似的项目,但我不需要做这样的事情。
The only way I can think of that might work for what you are trying to do is using Serialization that can be used to represent an object as a sequence of bytes and then that can be sent using ObjectOutputStream and received by using ObjectInputStream as they are required in sending/receiving Object.
Although I have worked on a similar project, i didn't require doing something like this.