posts - 41,  comments - 40,  trackbacks - 0

          前幾天自己發(fā)表的只運(yùn)行一個實(shí)例的文章,感謝Pande的留意,并提出寶貴意見,他推薦的正好是我想找的RSSOwl源碼,以下是我分析RSSOwl如何做到只運(yùn)行一個實(shí)例并且激活的,如有錯誤,請拍磚。

          http://sourceforge.krugle.com/kse/files/cvs/cvs.sourceforge.net/rssowl/RSSOwl/src/java/net/sourceforge/rssowl/controller/RSSOwlLoader.java

          根據(jù) RSSOwlLoader.java 中的

          [code]
          private static void startupProcess( String[] args )
          {
          ? ...

          ? if( !System.getProperties().containsKey( PROPERTY_ALLOW_MULTI_INSTANCES )&&StartupManager.isRSSOwlRunning( feedArgument ) )

          ? ...

          }
          [/code]

          追蹤到 StartupManager.java 見下:

          http://sourceforge.krugle.com/kse/files/cvs/cvs.sourceforge.net/rssowl/RSSOwl/src/java/net/sourceforge/rssowl/controller/thread/StartupManager.java

          追蹤到 StartupManager.isRSSOwlRunning( String message ) 用途為建立ServerSocket,監(jiān)聽本地8794端口

          [code]
          static ServerSocket applLockSocket;

          public static boolean isRSSOwlRunning( String message )
          {

          ? try{ applLockSocket=new ServerSocket( 8794, 50, InetAddress.getByName( "127.0.0.1" ) );? //1987年9月4日出生?

          ?????? handleSocketUnBound();? //

          ?????? return false;
          ???? }
          ? catch( java.net.BindException e )??? //Another instance already running
          ?????? {
          ???????? ...

          ???????? handleSocketBound( message );? //

          ???????? return true;
          ?????? }?
          ? catch( IOException e )? //Other Error
          ?????? {
          ???????? ...

          ???????? return false;
          ?????? }
          }
          [/code]

          追蹤到 StartupManager.handleSocketUnBound() 和 StartupManager.handleSocketBound( String message )

          [code]
          private static void handleSocketBound( String message )
          {
          ? Socket socket;

          ? try{ socket=new Socket( InetAddress.getByName( "127.0.0.1" ), 8794 );

          ?????? PrintWriter writer=new PrintWriter( new OutputStreamWriter( socket.getOutputStream() ) );

          ?????? writer.println( ( message!=null&&message.length()>0 ) ? message : DEFAULT_MESSAGE );

          ?????? writer.flush();
          ???? }
          ? catch( UnknownHostException e )
          ?????? {
          ???????? ...
          ?????? }
          ? catch( IOException e )
          ?????? {
          ???????? ...
          ?????? }
          }
          [/code]

          [code]
          /**
          ?* Server not yet running. Start it and listen for incoming messages.
          ?*/
          private static void handleSocketUnBound()
          {
          ? listen();? //轉(zhuǎn)向,為了對稱好看?還是為了兼容?
          }

          /**
          ?* Listen for incoming messages.看看接受的連接發(fā)送了什么內(nèi)容
          ?*/
          private static void listen()
          {
          ? //Run the Server inside a Thread
          ? server=new ExtendedThread()? //extends from Thread
          ? {
          ??? public void run()
          ??? {
          ????? while( !isStopped()&&!isInterrupted() )
          ?????????? {
          ???????????? BufferedReader buffReader=null;

          ???????????? try{ //Read a single line from the Socket
          ????????????????? Socket socket=applLockSocket.accept();

          ????????????????? buffReader=new BufferedReader( new InputStreamReader( socket.getInputStream() ) );

          ????????????????? final String message=buffReader.readLine();

          ????????????????? socket.close();

          ????????????????? //Check the received message
          ????????????????? if( ( message!=null&&message.length()>0 )&&GUI.display!=null&&!GUI.display.isDisposed() )? //激活某個GUI的代碼在此,我們進(jìn)去看看
          ??????????????????? {
          ????????????????????? GUI.display.asyncExec( new Runnable()
          ????????????????????? {
          ??????????????????????? public void run()
          ??????????????????????? {
          ????????????????????????? //Restore the RSSOwl Window and handle Message
          ????????????????????????? if( GUI.isAlive() )
          ??????????????????????????? {
          ????????????????????????????? GUI.rssOwlGui.restoreWindow();? //找到了,轉(zhuǎn)到GUI.java

          ????????????????????????????? //Handle the message as Link if valid argument
          ????????????????????????????? if( RSSOwlLoader.isValidArgument( message ) )
          ??????????????????????????????? {
          ????????????????????????????????? GUI.rssOwlGui.getEventManager().actionHandleSuppliedLink( message );
          ??????????????????????????????? }
          ??????????????????????????? }
          ??????????????????????? }
          ????????????????????? } );
          ??????????????????? }
          ??????????????? }
          ???????????? catch( IOException e )
          ????????????????? {
          ??????????????????? ...
          ????????????????? }
          ???????????? finally{ //關(guān)閉流
          ??????????????????? }
          ?????????? }
          ??? }
          ? };

          ? server.setDaemon( true );

          ? server.setName( "Startup Manager Thread" );

          ? server.start();
          }
          [/code]

          追蹤到 GUI.java 見下:

          http://sourceforge.krugle.com/kse/files/cvs/cvs.sourceforge.net/rssowl/RSSOwl/src/java/net/sourceforge/rssowl/controller/GUI.java

          追蹤到GUI.restoreWindow()

          [code]
          /**
          ?* Restore the application window either from taskbar or the tray.
          ?*/
          public void restoreWindow()
          {
          ? //RSSOwl is minimized to Tray
          ? if( GlobalSettings.useSystemTray()&&rssOwlSystray!=null&&rssOwlSystray.isMinimizedToTray() )
          ??? {
          ????? rssOwlSystray.restoreWindow();
          ??? }
          ? else{ //RSSOwl is not active
          ??????? shell.forceActive();? //就是它了

          ??????? shell.setMinimized( false );
          ????? }
          }
          [/code]

          原理如下:

          在本地8794端口建立服務(wù)監(jiān)聽,并且一直監(jiān)聽此端口,試圖接受此端口其它實(shí)例(其它程序?)發(fā)送的輸入

          如果讀到數(shù)據(jù)(好像沒有判斷數(shù)據(jù)的合法性,僅僅判斷數(shù)據(jù)不為空),并且自己不是“激活”狀態(tài),就“激活”自己;

          如果建立服務(wù)監(jiān)聽不成功,說明已經(jīng)有實(shí)例(其它程序?)占用此端口了,向此端口發(fā)送數(shù)據(jù)喚醒前一個實(shí)例,停幾秒以便前一個實(shí)例接受,然后退出。

          程序用的是SWT,激活方法用的是shell.forceActive(),but it's not good for core java.

          以上分析如有不對,懇請斧正。



          ?

          posted on 2007-09-01 17:03 NeedJava 閱讀(1473) 評論(1)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 西藏| 辽宁省| 乌拉特后旗| 文成县| 承德县| 南阳市| 外汇| 桃园县| 镇平县| 玛多县| 曲麻莱县| 苗栗市| 马龙县| 宜章县| 盘山县| 西乌| 遵义市| 六安市| 绥芬河市| 肃南| 扬中市| 巴塘县| 龙江县| 定边县| 遂平县| 灵武市| 北京市| 凤凰县| 沐川县| 阳曲县| 开原市| 西乌珠穆沁旗| 新龙县| 攀枝花市| 定结县| 岳阳县| 张家界市| 宁海县| 枞阳县| 中阳县| 长沙县|