Socket Java, два клиента, один сервер

328
24 апреля 2017, 02:21

Реализовать игру крестики-нолики (два клиента, один сервер). Сервер принимает ход клиента, изменяет объект класса Field (поле крестиков-ноликов), НО! Во-первых выводит сразу сообщения от двух клиентов, хотя ответил только один, во-вторых в объекте Field f (далее просто f) у сервера все нормально обновляется, а вот к клиентам приходит самый первый f (когда походил первый) и не обновляет его. Как синхронизировать ответы?

Код сервера

public class Server {
    public Server() {
        ServerSocket server = null;
        Socket client1 = null;
        Socket client2 = null;
        try {
            server = new ServerSocket(Protocol.PORT);
            client1 = server.accept();
            client2 = server.accept();
            Resender r = new Resender(client1, client2);
            r.run();
            server.close();
        } catch (IOException e) {
            System.exit(-1);
        }
    }
    private class Resender {
        private boolean stoped;
        Socket client1 = null;
        Socket client2 = null;
        Field f = null;
        ObjectOutputStream out1 = null;
        ObjectOutputStream out2 = null;
        ObjectInputStream in1 = null;
        ObjectInputStream in2 = null;
        public Resender(Socket s1, Socket s2) {
            try {
                client1 = s1;
                client2 = s2;
                out1 = new ObjectOutputStream(client1.getOutputStream());
                in1 = new ObjectInputStream(client1.getInputStream());
                out2 = new ObjectOutputStream(client2.getOutputStream());
                in2 = new ObjectInputStream(client2.getInputStream());
                f = new Field();
            } catch (IOException ex) {
                Logger.getLogger(Server.class.getName())
                        .log(Level.SEVERE, null, ex);
            }
        }
        public void setStop() {
            stoped = true;
        }

        public void run() {
            try {
                while (true) {
                    if (move(in1, 'x') || move(in2, 'o'))
                        break;
                }
                out1.close();
                out2.close();
                in1.close();
                in2.close();
                client1.close();
                client2.close();
            } catch (Exception ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        private boolean move(ObjectInputStream in, char c) {
            try {
                MessageMove msg = (MessageMove) in.readObject();
                int move = f.move(c, msg.getX());
                f.sout();
                out1.writeObject(f);
                out2.writeObject(f);
                if (move == f.Win)
                    return true;
            } catch (Exception ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
            return false;
        }
    }
}

Код клиента

public class Client {
    static Socket server;
    static ObjectOutputStream out;
    static ObjectInputStream in;
    public Client() {
        try {
            server = new Socket(Protocol.HOST, Protocol.PORT);
            out = new ObjectOutputStream(server.getOutputStream());
            in = new ObjectInputStream(server.getInputStream());
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Play!");
        Resender resend = new Resender();
        resend.run();
    }
    private class Resender {
        private boolean stoped;
        public void setStop() {
            stoped = true;
        }
        public void run() {
            Scanner sc = new Scanner(System.in);
            Field f = null;
            int x;
            while (true) {
                try {
                    x = sc.nextInt();
                    out.writeObject(new MessageMove(x));
                    f = (Field) in.readObject();
                    f.sout();
                } catch (Exception ex) {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}

Код Field

public class Field implements Serializable {
    private static final long serialVersionUID = 1L;
    public final int CellIsBusy = -1;
    public final int SuccessMove = 0;
    public final int Win = 1;
    private int size = 3;
    private char[] field = {'_', '_', '_',
            '_', '_', '_',
            '_', '_', '_'};
    private int[] canvas = {0, 1, 2,
            3, 4, 5,
            6, 7, 8,
            0, 4, 8,
            6, 4, 2,
            0, 3, 6,
            1, 4, 7,
            2, 5, 8};
    public Field() {
    }
    public int move(char c, int i) {
        if (field[i] != '_')
            return CellIsBusy;
        field[i] = c;
        sout();
        return isWin();
    }
    private int isWin() {
        char x = 'x', o = 'o';
        for (int i = 0; i < 8 * 3; i += 3) {
            int j = 0;
            for (; j < size; j++)
                if (x != field[canvas[i + j]])
                    break;
            if (j == size)
                return Win;
            j = 0;
            for (; j < size; j++)
                if (o != field[canvas[i + j]])
                    break;
            if (j == size)
                return Win;
        }
        return SuccessMove;
    }
    public char atIndex(int i) {
        return field[i];
    }
    public void sout() {
        for (int j = 0, k = 1; j < size * size; j++, k++) {
            System.out.print(field[j] + " ");
            if (k % 3 == 0)
                System.out.println();
        }
        System.out.println();
        System.out.println();
    }
}
READ ALSO
Первый раз отправляется get запрос, 2 раз нет

Первый раз отправляется get запрос, 2 раз нет

Вот, где обрабатывается запрос и при выборе элемента в списке снова запускается с новым параметром q:

220
Как изменить значение в Firebase

Как изменить значение в Firebase

Как изменить значение child-a в firebase?

427
Ошибка при взятии скриншота элемента

Ошибка при взятии скриншота элемента

ЗдравствуйтеНа сайте понадобилось заскринить каптчу, причем со страницы именно её

263
В чём разница между &#171;import java.util.*&#187; и &#171;import java.util.Scanner&#187;

В чём разница между «import java.util.*» и «import java.util.Scanner»

Вместо Scanner может быть что угодно - суть яснаА именно: зачем использовать второй вариант, если первый и набирать короче, и пригодится когда...

224