我试图构建一个多人游戏,游戏服务器最多与4个客户端一起操作,使用java套接字和ServerSocket。在此代码中,我将客户端限制为1,用于测试,并对播放器和服务器使用阻塞I/O模型。
游戏服务器线程(实现可运行)使用套接字输入流从每个客户端接收'Snake对象到snakei‘和'char变量到dirInput’,并使用socket输出流发送'Snake object Array snake‘和'Apple apple。Snake对象和Apple对象都是可序列化的。
在这里,clientSocket数组包含所有连接的客户端套接字,而这些套接字直到播放器结束连接才关闭(这意味着每个播放器的整个游戏都用一个套接字完成)。板对象扩展了游戏图形的JComponent (显示游戏游戏)。
public void run()
{
while(true)
{
//playerCount is fixed to 1 for testing
for(int i=0; i<playerCount; i++)
{
try {
//get every snake object from each player
ObjectInputStream objectInputStream = new ObjectInputStream(clientSocket[i].getInputStream());
snake[i] = (Snake)objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
for(int i=0; i<playerCount; i++)
{
try {
Reader charInputStream = new InputStreamReader(clientSocket[i].getInputStream());
dirInput = (char) charInputStream.read();
//DO SOMETHING WITHOUT COMMUNICATION
} catch (IOException e) {
e.printStackTrace();
}
}
for(int i=0; i<playerCount; i++)
{
try {
OutputStream outputStream = clientSocket[i].getOutputStream();
outputStream.write(i);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(clientSocket[i].getOutputStream());
objectOutputStream.writeObject(snake);
objectOutputStream.writeObject(apple);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}每个inputControl‘播放器客户端线程(实现可运行)向服务器发送'Snake object mySnake’和'char变量‘,并从服务器接收'int变量到playerNumber','Snake object和从服务器接收'Apple到board.apple’‘。
public void run() {
while(true)
{
try {
Thread.sleep(50);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(gameSocket.getOutputStream());
objectOutputStream.writeObject(mySnake);
Writer charOutputWriter = new OutputStreamWriter(gameSocket.getOutputStream());
charOutputWriter.write(inputControl);
playerNumber = gameSocket.getInputStream().read();
ObjectInputStream objectInputStream = new ObjectInputStream(gameSocket.getInputStream());
board.snakes = (Snake[])objectInputStream.readObject();
board.apple = (Apple)objectInputStream.readObject();
mySnake = board.snakes[playerNumber];
board.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
}问题是,当我同时启动游戏服务器和客户端并尝试进行通信时,游戏服务器线程和Player客户端线程在通信时都会出现问题。
当我调试时,游戏服务器线程被从客户端线程读取字符输入(dirInput)所困,客户端线程则被从游戏服务器线程读取int输入(playerNumber)所卡住。通过看到两个线程都使用InputStream,我认为在使用InputStream时出现了死锁,因为两个线程都试图使用InputStream。但我不确定僵局是否真的发生了。
如何使两个线程进行通信?游戏服务器线程和播放器客户端线程都应该使用非阻塞I/O模型吗?
发布于 2019-05-13 00:49:44
我不知道你到底做了什么!但问题是,您已经多次创建了ObjectInputStream!如果您想知道问题所在,只需创建一个简单的类来扩展java.io.InputStream类,并通过将该类作为基本的InputStream来创建一个ObjectInputStream。您将看到当ObjectInputStream类创建时,它将尝试将4个字节读入头字节!这意味着你丢失了一些数据,这也是你的线程卡住的原因!如果您有反编译器,也可以检查ObjectInputStream的代码。
https://stackoverflow.com/questions/56013864
复制相似问题