Проблема с блокировкой сетевой задачи - PullRequest
2 голосов
/ 27 апреля 2010

Я новичок в Java, поэтому прошу прощения за любые непристойные ошибки, которые я могу совершить:)

Я разрабатываю программу на Java, которая, помимо прочего, должна также обрабатывать клиентов, которые будут подключаться к серверу. На сервере запущены 3 потока, и я создал их следующим образом:

DaemonForUI du;
DaemonForPort da;
DaemonForCheck dc;

da = new DaemonForPort(3);
dc = new DaemonForCheck(5);
du = new DaemonForUI(7);

Thread t_port = new Thread(da);
Thread t_check = new Thread(dc);
Thread t_ui = new Thread(du);

t_port.setName("v1.9--PORTd");
t_check.setName("v1.9-CHECKd");
t_ui.setName("v1.9----UId");

t_port.start();
t_check.start();
t_ui.start();

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

Если я также настрою запуск потока t_ui, то вся программа блокируется при «принятии» потока t_ui.

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

public ServerSocketChannel ssc = null;

ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(port));
ssc.configureBlocking(false);

SocketChannel sc = ssc.accept();

if (sc == null) {
    ;
}
else {
    System.out.println("The server and client are connected!");
    System.out.println("Incoming connection from: " + sc.socket().getRemoteSocketAddress());
    in = new DataInputStream(new BufferedInputStream(sc.socket().getInputStream()));
    out = new DataOutputStream(new BufferedOutputStream(sc.socket().getOutputStream()));
    //other magic things take place after that point...

Поток для t_ui создается следующим образом:

class DaemonForUI implements Runnable{
    private int cnt;
    private int rr;
    public ListenerForUI serverListener;

    public DaemonForUI(int rr){
        cnt = 0;
        this.rr = rr;
        serverListener = new ListenerForUI();
    }

    public static String getCurrentTime() {
        final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
        return (sdf.format(cal.getTime()));
    }


    public void run() {
        while(true) {
            System.out.println(Thread.currentThread().getName() + "\t (" + cnt + ")\t (every " + rr + " sec) @ " + getCurrentTime());
            try{
                Thread.sleep(rr * 1000);
                cnt++;
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

Очевидно, что я делаю что-то не так при создании сокета или при использовании потока. Знаете ли вы, что является причиной проблемы?

Буду признателен за любую помощь.

Ответы [ 2 ]

1 голос
/ 28 апреля 2010

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

0 голосов
/ 28 апреля 2010

Проблема решена :) Я посмотрел на ваши предложения и присмотрелся к коду. Это была ошибка проектирования, так как у меня была функция, которая создала цикл while (true) внутри конструктора DaemonForUI (а точнее внутри ListenerForUI ()). Это заставляло всю программу циклически проходить через оператор while, поэтому останавливало все остальные действия.

Глупая ошибка, я должен признать ...: (

Спасибо всем за помощь всем, кто ответил на мой вопрос.

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

...