Попытка написать многопользовательскую игру-змею с сервером и клиентами через сокеты
, поэтому, если один клиент подключается, все работает нормально, но как только второй подключается, первый перестает получать сервер данных.
Код сервера
private void serverGo() {
try {
ServerSocket serverSocket = new ServerSocket(6667);
while (true) {
Socket shakeSocket = serverSocket.accept();
Socket receiverSocket = serverSocket.accept();
System.out.println("receiver client connected!");
Socket senderSocket = serverSocket.accept();
System.out.println("sender client connected!");
oos = new ObjectOutputStream(shakeSocket.getOutputStream());
oos.writeObject(playerId);
oos.flush();
oos.reset();
oos.close();
clientNbr++;
//System.out.println("player id " +playerId+ " connected");
if(clientNbr==1){
apple();
Thread t1 = new Thread(new GameRun());
t1.start();
clientNbr=0;
}
Thread t = new Thread(new ClientHandler(senderSocket, receiverSocket));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ClientHandler implements Runnable {
private Socket sender;
private Socket receiver;
public ClientHandler(Socket sender, Socket receiver) {
this.sender=sender;
this.receiver=receiver;
playersMap.put("player" + playerId, new Player(playerId, snakeSetUp(), 5, 0));
playerId++;
System.out.println("players map size " +playersMap.size());
}
@Override
public void run() {
try {
oos = new ObjectOutputStream(sender.getOutputStream());
ois = new ObjectInputStream(receiver.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
try { //receiving
String playerId;
while ((playerId = (String.valueOf(ois.readObject()))) != null) {
int x = (int) ois.readObject();
int y = (int) ois.readObject();
Player p = playersMap.get("player" +playerId);
p.setMoveX(x);
p.setMoveY(y);
playersMap.replace("player"+playerId,p);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class GameRun implements Runnable {
@Override
public void run() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
for (String player : playersMap.keySet()) {
Player p = playersMap.get(player);
//System.out.println(p.getPlayerId()+" "+player);
int x = p.getSnake().get(0).getX() + p.getMoveX() * 2;
int y = p.getSnake().get(0).getY() + p.getMoveY() * 2;
if (x >= 500) {
x -= 500;
}
if (y < 0) {
y += 500;
}
if (x < 0) {
x += 500;
}
if (y >= 500) {
y -= 500;
}
p.snakeAdd(new Snake(x, y));
p.snakeRemove();
for (int i = 1; i < p.getSnake().size(); i++) {
if (p.getSnake().get(0).equals(p.getSnake().get(i))) {
timer.purge();
timer.cancel();
}
}
if (p.getSnake().get(0).equals(apple)) {
score += 3;
p.getSnake().add(new Snake(p.getSnake().get(0).getX() - p.getMoveX() * 2,
p.getSnake().get(0).getY() - p.getMoveY() * 2));
apple();
}
}
sendData();
}
}, 300, 75);
}
}
private void sendData(){
try {
oos.writeObject(playersMap);
oos.writeObject(apple);
oos.flush();
oos.reset();
System.out.println("send");
} catch (IOException e) {
e.printStackTrace();
//timer.cancel();
}
}
код клиента
private void multiPlayerLobbyPlusGui(){
try {
Socket shake = new Socket("127.0.0.1", 6667);
Socket sender = new Socket("127.0.0.1", 6667);
receiver = new Socket("127.0.0.1", 6667);
ois = new ObjectInputStream(shake.getInputStream());
try {
playerID= (int) ois.readObject();
System.out.println("players ID "+playerID);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ois = new ObjectInputStream(receiver.getInputStream());
System.out.println("receiver connected!");
oos = new ObjectOutputStream(sender.getOutputStream());
System.out.println("sender connected!");
}catch (IOException e) {
e.printStackTrace();
}
JPanel multiPanel = new JPanel();
multiPanel.setBackground(Color.black);
multiPanel.setLayout(new BoxLayout(multiPanel, BoxLayout.Y_AXIS));
multiPanel.setPreferredSize(new Dimension(mainPanelW, mainPanelH));
String[] menuArray = new String[]{"Start", "Exit"};
JList<String> multiJList = new JList<>(menuArray);
multiJList.setFont(new Font(null, Font.BOLD, 25));
DefaultListCellRenderer renderer = (DefaultListCellRenderer) multiJList.getCellRenderer();
renderer.setHorizontalAlignment(SwingConstants.CENTER);
multiJList.setBackground(Color.black);
multiJList.setForeground(Color.white);
multiJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
multiJList.setSelectionBackground(Color.black);
multiJList.setSelectionForeground(Color.gray);
UIManager.put("List.focusCellHighlightBorder", BorderFactory.createEmptyBorder());
indexList=0;
multiJList.addListSelectionListener(e -> {
if (!e.getValueIsAdjusting()) {
indexList = multiJList.getSelectedIndex();
}
});
multiJList.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "multiAction");
multiJList.getActionMap().put("multiAction", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (indexList == 0) { //start
frame.remove(multiPanel);
//sendData(playerID, -pixMove, 0);
multiPlayerGo();
} else if (indexList == 1) { //exit
frame.remove(multiPanel);
menuGui();
}
}
});
multiPanel.add(Box.createVerticalGlue());
multiPanel.add(multiJList);
multiPanel.add(Box.createVerticalGlue());
frame.getContentPane().add(multiPanel);
frame.pack();
multiJList.requestFocusInWindow();
multiJList.setSelectedIndex(indexList);
}
private void multiPlayerGo() {
gameGui();
Thread t = new Thread(new ReceivingData());
t.start();
mainPanel.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "left");
mainPanel.getActionMap().put("left", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (moveX != pixMove) {
sendData(playerID, -pixMove, 0);
}
}
});
mainPanel.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "right");
mainPanel.getActionMap().put("right", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (moveX != -pixMove) {
sendData(playerID, pixMove, 0);
}
}
});
mainPanel.getInputMap().put(KeyStroke.getKeyStroke("UP"), "up");
mainPanel.getActionMap().put("up", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (moveY != pixMove) {
sendData(playerID, 0, -pixMove);
}
}
});
mainPanel.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "down");
mainPanel.getActionMap().put("down", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (moveY != -pixMove) {
sendData(playerID, 0, pixMove);
}
}
});
mainPanel.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "esc");
mainPanel.getActionMap().put("esc", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
try {
receiver.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
mainPanel.requestFocusInWindow();
}
private class ReceivingData implements Runnable{
@Override
public void run() {
try{
while ((playersMap = (LinkedHashMap<String, Player>) ois.readObject())!=null){
apple=(Snake) ois.readObject();
System.out.println("receiving");
for(String s: playersMap.keySet()){
if(playerID==playersMap.get(s).getPlayerId()){
snakePos=playersMap.get(s).getSnake();
//snake1.clear();
}else{
snake1=playersMap.get(s).getSnake();
}
}
mainPanel.updateUI();
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private void sendData(int pId, int x, int y){
try {
oos.writeObject(pId);
oos.writeObject(x);
oos.writeObject(y);
oos.flush();
oos.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
, поэтому я не получаю никаких ошибок во время выполнения или чего-либо еще, только первый клиент перестает получать, и если 3-й соединитель первый 2 прекращает получать данные, пробовал новый поток для отправки серверу форм, который иногда не помог просто получить ошибки одновременного выполнения. Ход идей, как это сделать.