Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как избежать запуска второй копии программы, Если прокрамма использует сокет по назна 
V
    Опции темы
Zefick
Дата 12.1.2010, 07:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.12.2009

Репутация: 1
Всего: 2



  Su_, я не понимаю, почему Вы отмели идею о занятии порта. Мне она пришла в голову сразу, как только я прочитал название темы (наверное, потому что в универе не так давно была лаба по сетевым приложениям на Java и что будет, если запустить два сервера я отлично помню). К тому же Вы говорите, что порт у вас и так занимается. Вот и замечательно - при второй попытке его занять выбросится исключение, которое надо ловить и передавать фокус в первую программу.

PM MAIL   Вверх
Su_
Дата 12.1.2010, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 386
Регистрация: 1.8.2007

Репутация: нет
Всего: нет



Сейчас я её реализовал правда на другом порте.,т.к на основной не хочеться кидать, иногда в процессе работы (прием сообщений ) вылетает исключение в ожидание порта ,потом пересоздается. С лок-файлом наиболее красивое решение, не надо занимать сетевой порт ,и не должно висеть порт,что если на этот порт начнут спамить ,и он выкинеть исключение)


--------------------
user posted image

PM MAIL WWW   Вверх
Su_
Дата 12.1.2010, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 386
Регистрация: 1.8.2007

Репутация: нет
Всего: нет



а как передать фокус в первую программу?


--------------------
user posted image

PM MAIL WWW   Вверх
serger
Дата 12.1.2010, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 19.6.2007
Где: Ижевск

Репутация: 1
Всего: 5



Грубо.
Занятие порта хорошая идея, до тех пор пока есть сеть.
В последнее время сеть, правда, уже почти везде...


--------------------
упс!
PM MAIL WWW Skype GTalk Jabber   Вверх
Su_
Дата 12.1.2010, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 386
Регистрация: 1.8.2007

Репутация: нет
Всего: нет



а как передать фокус в первую программу?

Добавлено через 1 минуту и 14 секунд
в смысле ГРубо? там мегафон интернет который иногда отваливается ..


--------------------
user posted image

PM MAIL WWW   Вверх
Su_
Дата 12.1.2010, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 386
Регистрация: 1.8.2007

Репутация: нет
Всего: нет



решил вопрос о восстановление фокуса,правда если через порт делать..

т.е. вешаю порт на сервер, если вылетает исключение шлю на этот же порт connect , а если на этом порту срабатывает accept то он делать

Код

setExtendedState(MAXIMIZED_BOTH);


т.е так :
Код

while(true)
      {
s = ss.accept();
prints("Восстановление окна");
setExtendedState(MAXIMIZED_BOTH);
    }
    }
    catch(Exception ioe)
    {
      //    block_multi_sender=false;
      System.out.println(ioe.toString());
      try
    {
      Socket s_block = new Socket();

      s_block.connect(new InetSocketAddress(myadress,Port2),200);
      }catch(Exception f)
    {

      }
      System.exit(0);
     //  prints("Принудительный сброс соединения");
     // prints("Данный порт уже занят!!!Закройте все приожения кроме одного и нажмите кнопку 'перезапустить TCP'.Попытка перезапустить ТСП автоматически...");
         // Закрываем соединение
     }




--------------------
user posted image

PM MAIL WWW   Вверх
dobrolub
Дата 12.1.2010, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 385
Регистрация: 18.12.2009
Где: Vancouver, Canada

Репутация: 11
Всего: 16



хороший способ; другой, кросс-платформный, трудно найти я думаю.
PM   Вверх
Su_
Дата 13.1.2010, 02:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 386
Регистрация: 1.8.2007

Репутация: нет
Всего: нет



будем тестировать, Важна стабильность)Спасибо всем кто помогал, я думаю топик можно закрыть)


--------------------
user posted image

PM MAIL WWW   Вверх
Viroman
Дата 15.6.2010, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 28.7.2008

Репутация: нет
Всего: нет



http://forum.vingrad.ru/forum/topic-303234.html

В продолжение этой темы, модер поспешил закрыть даже до конца не поняв сути, не конкретно незапуск второй копии, а именно шаринг списка задач, общий блок памяти, или ещё чего нибудь быстрое.
Порты занимать уже проходили, не то, глупый вариант, и я о нём уже думал, но видимо больше хороших идей нет :(
PM MAIL   Вверх
Viroman
Дата 11.7.2010, 16:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 28.7.2008

Репутация: нет
Всего: нет



Код

import java.io.*;
import java.nio.*;
public class T {
    public static void main(String[] args) throws Exception {
        System.out.println(new FileOutputStream("xxx").getChannel().tryLock());
        synchronized(T.class) {
            T.class.wait();
        }
    }
}

Кстати, просто обязан поблагодарить dobrolub за предоставленный код, работает на ура.
Только как я понял, дискуссия была по поводу нерабочести под линуском.
Так вот, если вдруг столкнётся кто то с этой проблемой вновь, есть одно огромное различие в плане использования этой фишки под виндой и линухом.
Дурость заключается в том, что при воспроизведении этого кода
 System.out.println(new FileOutputStream("xxx").getChannel().tryLock());
на винде файл лочится до конца воспроизведения всей джава машины!!! и работает как надо и ожидается, что так и будет работать, ведь никто лок программно не освобождает. Но на линухе это не работает, как ожидается!!! Фишка заключается в том, что если воспроизвести этот код
 System.out.println(new FileOutputStream("xxx").getChannel().tryLock());
то система залочит файл, а потом она его тут же разблокирует, к сожалению, и это и явилось подводным камнем и для меня, и похоже для топикстартера!!!
Дабы избежать этой проблемы в КОРНЕ, учтите на будущее,
запускайте выжеизложенный код как есть с синхронизацией и wait в отдельном потоке и тогда и файл лочится прекрасно и не разлочивается до конца воспроизведения машины, и работает и на винде, линухе, маке итп... Может кому то это поможет, чтобы на те же грабли не наступали..
PM MAIL   Вверх
koreyko
Дата 27.3.2013, 00:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 20.4.2010

Репутация: нет
Всего: нет



Здравствуйте, уважаемые форумчане.

Решил не открывать новую тему, т.к. стоит та же задача - сворачивание приложения в трей и его восстановление из трея при попытке запуска второй копии приложения. Задачу блокировки второй копии решил с помощью лок-файла. Осталось передать фокус в запущенную первой копию. 

Я пробую сделать это через instance ID. Получаю и сохраняю ID в залоченный файл, при запуске второй копии - считываю. Теперь остался последний шаг: достучаться к уже запущенному инстансу через его ID и восстановить окно программы. 

Подскажите, пожалуйста, как это сделать?

Спасибо.
PM MAIL   Вверх
COVD
Дата 27.3.2013, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

Теперь остался последний шаг: достучаться к уже запущенному инстансу через его ID и восстановить окно программы. 

Надо делать, как уже писали выше, все через порт. Приложение при запуске должно запускать сервер, который принимает сокетные соединения на любом свободном порту из заданного диапазона. Приложение должно провести поиск  других инстансев соединяясь поочередно к портам  из заданного диапазона. Если соединение успешно создано и пароль совпадает, значит два инстанса друг друга нашли и дальше могут обмениваться командами через сокетное соединение.
PM MAIL   Вверх
koreyko
Дата 27.3.2013, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 20.4.2010

Репутация: нет
Всего: нет



Спасибо, а где можно почитать об этом способе - через порт? Желательно с примерами. После прочтения ветки ясность не наступила, к сожалению.
PM MAIL   Вверх
COVD
Дата 27.3.2013, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43




Примерно так. 
Запустите этот класс два раза. Когда вторая инстанс стартует, первая закрывается командой System.exit(0). Можно любое другое поведение реализовать.

Код

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

/**
 * On application start ShutdownServer runs one time task.
 * Task searches another application instances on local computer and send shutdown command
 * if discovered instance runs with the same userID value.
 *
 * @author
 */
public class ShutdownServer {
    private static String thisApplicationUserID;
    private static int portDefault = 25000;
    private static int portRange = 5;
    private static int readTimeout  = 2000;// 2 sec
    private static boolean daemon  = true;// false, if started from main()
    
    
    private static final String COMMAND_HELLO = "HELLO";
    private static final String COMMAND_SHUTDOWN = "SHUTDOWN";
    private static Thread serverSocketThread;

    
    public static void start(String userID){
        thisApplicationUserID = userID;                
        Thread t = new Thread(){
            public void run(){                
                discoverInstances(); 
                startServer();
            }
        };       
        t.start();       
    }      
        
    /**
     * Method starts thread listening connections on first found available port from range 25000 .. 25004     
     */
    private static void startServer() {
        int port = portDefault;
        for (int i = 0; i < portRange; i++) {        
            try {                
                final ServerSocket serverSocket = new ServerSocket(port);    
                serverSocketThread = new Thread(){
                    public void run(){
                        runServerSocket(serverSocket);
                    }
                };  
                serverSocketThread.setDaemon(daemon);
                serverSocketThread.start();
                break;
            } catch (IOException ex) {                
            }
            port++;
        }
    } 
    
    /**
     * Method runs socket accept loop.
     * On input command COMMAND_HELLO thread responds with thisApplicationUserID value.
     * On input command COMMAND_SHUTDOWN thread shutdowns this application.
     */    
    private static void runServerSocket(ServerSocket serverSocket) {
        try {
            System.out.println("ShutdownServer starts on port: " + serverSocket.getLocalPort());
            while (!Thread.currentThread().isInterrupted()) {
                Socket socket = null;
                try {
                    
                    socket = serverSocket.accept();                    
                    socket.setSoTimeout(readTimeout);
                   
                    String request = readLine(socket);                                            

                    if (request == null) {
//                        System.out.println("runServerSocket: null input");
                        continue;
                    }


                    int index = request.indexOf(":");
                    if (index == -1) {
//                        System.out.println("runServerSocket: wrong format");
                        continue;
                    }


                    int portSent = -1;
                    try {
                        portSent = Integer.parseInt(request.substring(0, index));
                    } catch (Exception e) {
                    }

                    if (portSent == -1) {
//                        System.out.println("runServerSocket: wrong port: " + request);
                        continue;
                    }

                    if (portSent != serverSocket.getLocalPort()) {
//                        System.out.println("runServerSocket: not equal to current port: " + portSent + " != " + serverSocket.getLocalPort());
                        continue;
                    }

                    String command = request.substring(index + 1);
                    System.out.println("command:"+command);
                    
                    if (command.equals(COMMAND_HELLO)) {//respond this userID to another application 
                        String response = String.valueOf(serverSocket.getLocalPort()) + ":" + thisApplicationUserID;
                        printLine(socket, response);
                    } else if (command.equals(COMMAND_SHUTDOWN)) {//shutdown this application by command from another application    
                        System.out.println("app exits");
                        System.exit(0);
                    } else {
//                        System.out.println("runServerSocket: unsupported command:" + command);
                    }



                } catch (Exception ex) {
                    System.out.println("ShutdownServer:" + ex);                    
                } finally {                    
                    close(socket);
                }
            }
        } finally {            
            close(serverSocket);            
        }        
    }
    
    private static void printLine(Socket socket, String str) throws IOException{
        PrintWriter pw = new PrintWriter(socket.getOutputStream()); 
        pw.println(str);
        pw.flush();        
//        System.out.println("printLine:"+str);
    }
    
    private static String readLine(Socket socket) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = br.readLine();                      
//        System.out.println("readLine:"+line); 
        return line;
        
    }  
    
    private static void close(Object obj) {
        if (obj != null) {
            if (obj instanceof Socket) {
                try {
                    ((Socket) obj).close();
                } catch (IOException ex) {
                }
            }
            else
            if (obj instanceof ServerSocket) {
                try {
                    ((ServerSocket) obj).close();
                } catch (IOException ex) {
                }
            }                
        }
    }
    /**
     * Method perform open ports search on local computer in range 25000 .. 25004
     * If connection to another application instance is established then string like port:COMMAND_HELLO is sent.
     * If response received and it has the same format and parsed userID value is equal this application userID, than COMMAND_SHUTDOWN is send.
     * Another application instance will perform System.exit().     
     */    
    private static void discoverInstances() {
        int port = portDefault;
        for (int i = 0; i < portRange; i++) {
            Socket socket = null;
            try {
                socket = new Socket("127.0.0.1", port);
                socket.setSoTimeout(readTimeout);
                
                String request = String.valueOf(port) + ":" + COMMAND_HELLO;
                
                printLine(socket,request);
               
                String response = readLine(socket);                
                
                if (response != null) {
                    int index = response.indexOf(":");
                    if (index != -1) {
                        String uID = response.substring(index + 1);
                        if(thisApplicationUserID.equals(uID)){
                           close(socket);
                           socket = new Socket("127.0.0.1", port);                             
                           String command = String.valueOf(port) + ":" + COMMAND_SHUTDOWN;
                           printLine(socket,command);
                           System.out.println("ShutdownServer terminates instance on port:" + port); 
                        }                        
                    }
                }

            } catch (UnknownHostException ex) {
//                System.out.println("UnknownHostException:" + ex);                
            } catch(SocketTimeoutException ex){
//                System.out.println("SocketTimeoutException:" + ex);            
            } catch (IOException ex) {
//                System.out.println("IOException:" + ex);
            } finally {
               close(socket);
            }
            port++;
        }
                
    }
    
    public static void main(String[] a){  
        daemon = false;//when started from main
        start("TEST");
    }
}

PM MAIL   Вверх
koreyko
Дата 1.4.2013, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 20.4.2010

Репутация: нет
Всего: нет



COVD, спасибо. Вдумчиво изучил Ваш код, но так и не понял -- каким образом я все-таки могу получить из второй запущенной копии доступ к фрейму первой копии? Для того, чтобы развернуть свернутое в трей окно. 
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1250 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.