gpt4 book ai didi

java - Kryonet RMI,无法等待连接更新线程的响应

转载 作者:行者123 更新时间:2023-12-01 10:34:38 25 4
gpt4 key购买 nike

我想使用 LibGDX 和 Kryonet 库,使用 RMI 制作一个游戏。所以我创建了干净的项目。我现在想做的是,设置服务器监听端口 10048 并在新连接上打印客户端的名称,我将通过调用客户端类上的方法来获取该名称...

这是代码:

ICardsTableImpl.java

package clzola.cardstable.client;

public interface ICardsTableGameImpl {
public String getName();
}

CardsTableServer.java

package clzola.cardstable.server;

import clzola.cardstable.client.ICardsTableGameImpl;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Server;
import com.esotericsoftware.kryonet.rmi.ObjectSpace;
import com.esotericsoftware.minlog.Log;

import java.io.IOException;
import java.util.HashMap;


public class CardsTableServer extends Server {
private HashMap<Integer, Connection> connections;

public CardsTableServer() throws IOException {
connections = new HashMap<Integer, Connection>();
addListener(new NetworkListener(this));

Kryo kryo = getKryo();
ObjectSpace.registerClasses(kryo);
kryo.register(ICardsTableGameImpl.class);

bind(10048);
}

@Override
protected Connection newConnection() {
Player player = new Player();
addConnection(player);
return player;
}


public void addConnection(Connection connection) {
this.connections.put(connection.getID(), connection);
}

public Connection getConnection(int connectionId) {
return this.connections.get(connectionId);
}

public Connection removeConnection(int connectionId) {
return this.connections.remove(connectionId);
}

public static void main(String[] args) throws IOException {
Log.set(Log.LEVEL_DEBUG);
CardsTableServer server = new CardsTableServer();
server.start();
}
}

NetworkListener.java

package clzola.cardstable.server;

import clzola.cardstable.client.ICardsTableGameImpl;
import com.badlogic.gdx.Gdx;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.rmi.ObjectSpace;

public class NetworkListener extends Listener {
private CardsTableServer server;

public NetworkListener(CardsTableServer server) {
this.server = server;
}

@Override
public void connected(Connection connection) {
Player player = ((Player) connection);

ICardsTableGameImpl game = ObjectSpace.getRemoteObject(player, 0, ICardsTableGameImpl.class);
player.name = game.getName(); // This is where I get excpetion...

Gdx.app.log("Server", "Player name: " + player.name);
}

@Override
public void disconnected(Connection connection) {
server.removeConnection(connection.getID());
}
}

Player.java

package clzola.cardstable.server;

import com.esotericsoftware.kryonet.Connection;

public class Player extends Connection {
public String name;
}

CardsTableGame.java

package clzola.cardstable.client;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.rmi.ObjectSpace;

public class CardsTableGame extends ApplicationAdapter implements ICardsTableGameImpl {
SpriteBatch batch;
Stage stage;
Client client;
String name = "Lazar";
ObjectSpace objectSpace;

@Override
public void create () {
batch = new SpriteBatch();
stage = new Stage(new ScreenViewport(), batch);

try {
client = new Client();
client.start();

Kryo kryo = client.getKryo();
ObjectSpace.registerClasses(kryo);
kryo.register(ICardsTableGameImpl.class);

ObjectSpace objectSpace = new ObjectSpace();
objectSpace.register(0, this);
objectSpace.addConnection(client);

client.connect(5000, "127.0.0.1", 10048);
} catch (Exception e) {
Gdx.app.log("CardsTableGame", e.getMessage(), e);
}
}

@Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}

@Override
public String getName() {
return this.name;
}
}

运行后,我在服务器端遇到异常:

Exception in thread "Server" java.lang.IllegalStateException: Cannot wait for an RMI response on the connection's update thread.
at com.esotericsoftware.kryonet.rmi.ObjectSpace$RemoteInvocationHandler.waitForResponse(ObjectSpace.java:420)
at com.esotericsoftware.kryonet.rmi.ObjectSpace$RemoteInvocationHandler.invoke(ObjectSpace.java:408)
at com.sun.proxy.$Proxy0.getName(Unknown Source)
at clzola.cardstable.server.NetworkListener.connected(NetworkListener.java:24)
at com.esotericsoftware.kryonet.Server$1.connected(Server.java:48)
at com.esotericsoftware.kryonet.Connection.notifyConnected(Connection.java:214)
at com.esotericsoftware.kryonet.Server.acceptOperation(Server.java:417)
at com.esotericsoftware.kryonet.Server.update(Server.java:249)
at com.esotericsoftware.kryonet.Server.run(Server.java:372)
at java.lang.Thread.run(Thread.java:745)

我不知道为什么......我做错了什么?(这是我第一次尝试使用 RMI)

最佳答案

监听器由 Kryonet-update-thread 执行。该线程定期检查套接字以接收消息。调用 game.getName() 会让调用者等待,直到答案通过网络传递。如果你在更新线程上这样做,你可能会让你的服务器陷入死锁,因为 kryonet 无法收到它正在等待的答案,因为你阻塞了更新线程。这就是它抛出异常的原因。

rmi example中从 kryonet git 他们通过使用在自己的线程上工作的监听器解决了这个问题。

// The ThreadedListener means the network thread won't be blocked when waiting for RMI responses.
client.addListener(new ThreadedListener(new Listener() {
public void connected (final Connection connection) {
TestObject test = ObjectSpace.getRemoteObject(connection, 42, TestObject.class);
// Normal remote method call.
assertEquals(43.21f, test.other());
// Make a remote method call that returns another remote proxy object.
OtherObject otherObject = test.getOtherObject();
// Normal remote method call on the second object.
assertEquals(12.34f, otherObject.value());
// When a remote proxy object is sent, the other side recieves its actual remote object.
connection.sendTCP(otherObject);
}
}));

关于java - Kryonet RMI,无法等待连接更新线程的响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34845390/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com