Переход от блокирующего к неблокирующему вводу / выводу с помощью javanio - PullRequest
0 голосов
/ 28 марта 2011

я адаптирую этот код Как отправить и получить сериализованный объект в канале сокета мое моделирование в реальном времени для отправки объектов, но я сталкиваюсь с исключениями один за другим, потому что этот код блокирует по своей природе, как этот код можно преобразовать в неблокирующее с помощью javanio

  /*
     * Writer
     */
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    import java.net.InetSocketAddress;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;

    public class CleanSender implements Runnable {

        private SimManager SM;
        private BallState ballState = new BallState(10, 5);
        private ServerSocketChannel ssChannel;

        private Thread tRunSer = new Thread(this, "ServerSelectThread");

    public static void main(String[] args) throws IOException {

        CleanSender server = new CleanSender();
        server.startServer();

    }

    private void startServer() throws IOException {
        ssChannel = ServerSocketChannel.open();
        ssChannel.configureBlocking(true);
        int port = 2345;
        ssChannel.socket().bind(new InetSocketAddress(port));
        // SM = new SimManager(this, BS);
        // SM.start(); // GameEngine thread starting here
        tRunSer.start();
    }

    public void run() {
        try {
            SocketChannel sChannel = ssChannel.accept();

            while (true) {

                ObjectOutputStream oos = new ObjectOutputStream(sChannel
                        .socket().getOutputStream());
                oos.writeObject(ballState);
                System.out.println("Sending String is: '" + ballState.X + "'" + ballState.Y);
                oos.close();
                System.out.println("Sender Start");
                System.out.println("Connection ended");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Клиент: который постоянно ищет ответ от сервера

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;

public class CleanReceiver implements Runnable {

    private SocketChannel sChannel;
    private Thread receiverThread = new Thread(this, "receiverThread");


    private synchronized  void startServer() throws IOException {
         sChannel = SocketChannel.open();
         sChannel.configureBlocking(true);
         if (sChannel.connect(new InetSocketAddress("localhost", 2345))) {
             receiverThread.start();
         }
    }
public void run() {

    while (true) {
        try {
            ObjectInputStream ois = new ObjectInputStream(sChannel.socket()
                    .getInputStream());

            BallState s = (BallState) ois.readObject();
            System.out.println("String is: '" + s.X + "'" + s.Y);
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println("End Receiver");
    }
}


      public static void main(String[] args) 
        throws IOException, ClassNotFoundException {

            CleanReceiver rc=new CleanReceiver();
            rc.startServer();

            System.out.println("End Receiver");
        }
}

Будет ли этот проект работать в сценарии, когда серверу приходится постоянно подключать клиента и одновременно отправлять состояние моделирования уже подключенному клиенту? , я ищу взгляд экспертов.

спасибо,

jibbylala

Ответы [ 2 ]

1 голос
/ 28 марта 2011

Если вы используете ObjectInputStream или ObjectOutputStream, я предлагаю вам придерживаться блокирования ввода-вывода. Использование неблокирующих операций ввода-вывода с этими библиотеками в 10 раз сложнее без реальной выгоды.

Рассматривали ли вы использование ServerSocket и Socket вместо NIO. Это будет проще в использовании, и какие потоки объектов изначально были предназначены для использования,

0 голосов
/ 28 марта 2011

В вашем коде две основные проблемы:

  • Вы закрываете потоки после обработки каждого отдельного объекта, что вызывает закрытие связанных сокетов, поэтому они больше не действительны и не могут использоваться для обработки следующих объектов. На приемной стороне вам вообще не нужно close() в цикле, на отправляющей стороне используйте flush() вместо close(), чтобы обеспечить сброс буферов.

  • При реализации блокировки ввода-вывода вам (как правило) необходимо запустить новый поток на сервере для каждого клиента. Это позволит вам общаться с несколькими клиентами одновременно. Остерегайтесь проблем с синхронизацией потоков в этом случае!

Если наличие потока для каждого клиента неприемлемо для вас, вы можете внедрить сервер неблокирующим способом, но, как уже сказал Питер Лори, это более сложно, поэтому я предлагаю вам заставить его работать с блокирующим вводом-выводом первый.

...