我正在做一个我需要创建一个java服务器和一些客户端的项目,以便客户端可以在服务器上播放tic-tac-toe。客户端和服务器将在同一个网络中,所以IP不会有任何问题,它们总是一样的。现在针对这个问题,只有两个玩家一起玩一个匹配,但是会有多个匹配运行,所以服务器应该处理它。我遇到的问题是我在服务器上使用线程来交换客户端之间的移动,我不知道如何使一个线程只与另一个线程通信,而不通知或与其他线程交互它目前没有参加比赛。 有没有办法从其他线程中隔离两个线程? 我无法上传任何代码,因为我甚至不知道从哪里开始。
感谢。
答案 0 :(得分:1)
由于您处于专用网络并使用套接字,因此您可以使用每个客户端的地址进行识别,您可以将一个对象作为同步对象分配给两个客户端,以便进行线程间通信。
答案 1 :(得分:0)
此问题与聊天应用类似。尝试查看任何基于xmpp的应用程序服务器(openfire)
答案 2 :(得分:0)
如果您的整个游戏都在一个套接字上进行,那么您就没有问题。当您的服务器套接字接受时,创建一个线程,并让该线程处理该套接字。没有其他线程甚至在范围内有该套接字。
如果你希望每个游戏都在一个单独的套接字连接上移动,而一个寿命较长的线程维持游戏状态,那就更复杂了。
可能最简单的解决方案是每个服务器线程都有自己的服务器套接字,使用动态分配的端口。服务器将有一个众所周知的端口,在该端口上将协商一个新会话:
client server
connect (well known port) -------> accept (well known port)
request new game -------> create new server socket (dynamic port)
launch thread to listen on dynamic port
receive dynamic port num <------- respond with dynamic port num
connect (dynamic port) -------> (in thread) accept, handle game
play game on this socket -------> ...
有一些细节需要解决,比如是否保持第一个套接字打开,或者在协商后关闭它。
这是一个相当完善的模式(例如,它类似于FTP)。对于以这种方式工作的协议,防火墙可能会出现问题。
另一个选择是继续将所有请求发送到同一个端口,由单个ServerSocket
处理,并将请求发送到相应的线程。要做到这一点,你需要一个会话ID,这将是每个请求的一部分。
执行此操作的一种方法是为每个游戏线程创建一个队列。每个线程从队列中读取命令。调度程序将请求放在适当的队列上。
创建新游戏主题时:
// in the dispatcher
Queue<Request> queue = new LinkedBlockingQueue<>();
String sessionId = generateSessionId(); // UUID, whatever
gamequeues.put(sessionid, queue); // gameQueues is a Map<String,Queue<Request>>
Game game = new Game(queue, sessionId);
new Thread(game).start();
当您收到游戏活动请求时:
// also in the dispatcher
String sessionId = request.getSessionId(); // HTTP header, something from payload, whatever
queue.add(request);
// In the thread
while(game.isActive()) {
Request request = queue.take();
handle(request);
}
虽然我已经展示了使用JDK中的Queue类的简单实现,但是诸如各种JMS实现(例如ActiveMQ),Kafka,Redis之类的队列实现为您提供了更强大的抽象功能。例如,所有这些都允许您定义单个队列,但是消费者只能获取与标题匹配的消息(例如会话ID)。
在所有这些示例中,如果担心安全问题,则需要防止会话密钥窃取。
答案 3 :(得分:0)
两个线程在你正在使用的公共锁上相互通信。如果两个线程需要相互通信,那么在它们之间使用一个公共锁。