我正在为在服务器和客户端系统上运行的游戏创建聊天,当然还有服务器客户端系统上的游戏,但是我无法让我的多线程程序工作,而且我'我将在下面解释一下。我可以说服务器客户端系统在单线程时工作。
首先,我的连接类:
1XgbfFV
服务器和客户端类:
public class Connection {
private Server server;
private Client client;
private boolean serverChosen;
public Connection(){
server = new Server();
this.serverChosen = true;
}
public Connection(String IP){
client = new Client(IP);
this.serverChosen = false;
}
public synchronized void sendObjects(Object obj) throws IOException{
if(serverChosen){
server.sendObjects(obj);
}else{
client.sendObjects(obj);
}
}
public synchronized Object receiveObjects() throws ClassNotFoundException, IOException{
if(serverChosen){
return server.receiveObjects();
}else{
return client.receiveObjects();
}
}
public Object waitForObject() throws ClassNotFoundException, IOException{
int i = 0;
Object obj;
while(true){
obj = receiveObjects();
i++;
if(obj != null || i >= 100){
return obj;
}
}
}
}
I类运行所有内容的是Frame类:
public class Server implements Serializable{
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
//constructor
public Server(){
try{
server = new ServerSocket(8790, 10); //8798 is a dummy port for testing, this can be changed. The 100 is the maximum people waiting to connect.
try{
//Trying to connect and have conversation
waitForConnection();
setupStreams();
}catch(EOFException eofException){
}
} catch (IOException ioException){
ioException.printStackTrace();
}
}
//wait for connection, then display connection information
private void waitForConnection() throws IOException{
connection = server.accept();
}
//get stream to send and receive data
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
public ObjectOutputStream getOutput(){
return output;
}
public ObjectInputStream getInput(){
return input;
}
public void sendObjects(Object obj) throws IOException{
output.writeObject(obj);
output.flush();
}
public Object receiveObjects() throws IOException, ClassNotFoundException{
return input.readObject();
}
}
public class Client extends JFrame implements Serializable{
private static final long serialVersionUID = 1L;
private ObjectOutputStream output;
private ObjectInputStream input;
private String serverIP;
private Socket connection;
private boolean next = true;
//constructor
public Client(String host){
serverIP = host;
try{
connectToServer();
setupStreams();
}catch(EOFException eofException){
}catch(IOException ioException){
ioException.printStackTrace();
}
}
public Client(){
serverIP = "127.0.0.1";
try{
connectToServer();
if(next){
setupStreams();
}
}catch(EOFException eofException){
//t.append("Connection was terminated");
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//connect to server
private void connectToServer(){
int i = 0;
do {
try {
connection = new Socket(InetAddress.getByName(serverIP), 8790);
next = true;
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Server was not found, The program will try again in 1 second; number of tries left: " + (10-i));
next = false;
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
i++;
}
}while(!next && i<=10);
if(!next){
JOptionPane.showMessageDialog(null, "Unable to connect to the server. Make sure the I.P. adress is correct, the ports are not blocked, or a firewall has not prevented connections.... IDK man... it's just me and all of this code... maybe the server isn't even running??");
}
}
//set up streams
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
public ObjectOutputStream getOutput(){
return output;
}
public ObjectInputStream getInput(){
return input;
}
public void sendObjects(Object obj) throws IOException{
output.writeObject(obj);
output.flush();
}
public Object receiveObjects() throws ClassNotFoundException, IOException{
return input.readObject();
}
}
我不想在上面的构造函数中删除任何更多内容,以防它以某种方式导致问题(我怀疑但因为我找不到比安慰更安全的问题)
以下是NetworkSender和NetworkReceiver类:
public class Frame implements ActionListener{
private int width;
private int height;
private JFrame jframe;
private Board board;
private JTextArea textBox;
private JScrollPane pane;
private Connection connection;
private JTextArea userText;
private JScrollPane userPane;
private JButton send;
private NetworkReceiver net;
public Frame(int width, int height, Connection connection, Board player, Board opponent){
this.width = width;
this.height = height;
this.connection = connection;
board = new Board(player, opponent);
init();
textBox = new JTextArea("CHAT WINDOW");
textBox.setWrapStyleWord(true);
textBox.setLineWrap(true);
textBox.setBackground(Color.GRAY);
textBox.setBounds(height, 0, width - (height) - 20, height-40);
textBox.setEditable(false);
userText = new JTextArea("Enter Messages Here");
userText.setWrapStyleWord(true);
userText.setLineWrap(true);
userText.setBackground(Color.WHITE);
userText.setBounds(height, height-40, width - (height) - 20, 40);
pane = new JScrollPane(textBox,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
pane.setBounds(height, 0, width - (height), height-40);
userPane = new JScrollPane(userText,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
userPane.setBounds(height, height-40, width - (height) - 20, 40);
send = new JButton();
send.setIcon(Utility.getImageIcon(Utility.getBufferedImage(Assets.send)));
send.setBounds(width - 20, height - 40, 20, 40);
send.addActionListener(this);
send.setBackground(Color.WHITE);
jframe = new JFrame();
jframe.setBackground(Color.DARK_GRAY);
jframe.getContentPane().setPreferredSize(new Dimension(width, height));
jframe.setLayout(null);
jframe.pack();
jframe.setLocationRelativeTo(null);
jframe.add(pane);
jframe.add(userPane);
jframe.add(send);
for(Space[] s: board.getSpaces()){
for(Space space: s){
jframe.add(space);
}
}
for(Space[] s: board.getSpaces()){
for(Space space: s){
space.addActionListener(this);
}
}
for(Space[] s: board.getSpaces()){
for(Space space: s){
if(space.getTile() != null){
space.setBackground(space.getTile().getColor());
}
}
}
for(Space[] s: board.getSpaces()){
for(Space space: s){
if(space.getPiece() != null){
space.setIcon(Utility.getImageIcon(space.getPiece().getImage()));
}
}
}
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setVisible(true);
net = new NetworkReceiver(connection, this);
net.start();
}
private void init(){
//stuff
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == send){
send();
}
}
private synchronized void send() {
String message = "YOU- " + userText.getText();
userText.setText("");
String totalMessage = textBox.getText();
textBox.setText(totalMessage + "\n" + message);
new NetworkSender(connection, message).start();
}
public synchronized void showMessage(String s){
String totalMessage = "Opponent- " + textBox.getText();
textBox.setText(totalMessage + "\n" + s);
}
破解的确切位置在NetworkSender类中。在控制台中,我收到&#34;尝试发送&#34;但从未发送过。&#34;这让我认为我设置线程错误,线程无法相互通信(发送方和接收方线程),或者服务器/客户端系统不正确地进行多线程。
我已经广泛地查找了这个问题,但是我无法在任何有效的地方找到解决方案,所以如果我有一个解决方案,我会道歉。如果一切都结束了,我可以根据需要发布我的连接,服务器和客户端类,但我认为它们是正常的,因为它们在EDT上工作。当我在网上搜索近4个小时时,我会问你,如果你认为这是一个重复的问题,你首先评论一个链接,因为我几乎可以肯定我已经看到它已经大声笑了。
答案 0 :(得分:1)
直接原因是您在Connection对象本身上同步接收和发送。当一个线程在receiveObjects()内时,没有其他线程可以输入send或receiveObjects()。因此,您的接收线程会永久阻止您发送。
您可以通过从连接类中的方法中删除synchronized来使其工作,而是使客户端和服务器上的相应方法在选定的不同对象上同步,例如相应的输入/输出-streams。
尽管如此,它仍然是一个设计狂欢者(这里没有说话)。您最好的行动方案可能是重新考虑设计 - 您选择的抽象(或缺乏)以及您在分配职责方面做出的选择留有改进的余地。