2012-11-13 55 views
0

我一直在嘗試創建一個本地進程,它將充當我的服務器的CLI。這個想法類似於DrushDrupal服務器的做法。在服務器和本地進程之間創建通信流

我還沒有創建CLI界面(可能會使用第三方代碼),但我想分享我的解決方案,以解決我在此問題上遇到的最大障礙:將本地進程之間的消息傳輸到正在運行的活動服務器使用REST服務是因爲它們會增加一些命令的安全風險。

回答

0

注:此代碼是寫在Scala,但可以轉換爲Java

首先我們需要創建一個擴展HttpServlet的一個servlet類。對於每個GET請求,servlet類將檢查我們的線程(稍後解釋)是否已打開,如果未嘗試啓動它。請注意,我們在啓動方法中使用try catch,因爲如果線程的狀態爲TERMINATED isAlive將返回true(我不知道爲什麼)。

我還實施了destroy方法來殺死我們的線程,如果servlet死亡。我不知道會發生什麼,如果該servlet死正在運行的線程,但以防萬一...

Servlet.scala:

package com.example 

import javax.servlet.http.HttpServlet 
import javax.servlet.http.HttpServletRequest 
import javax.servlet.http.HttpServletResponse 

class Servlet extends HttpServlet { 

    override def doGet(req: HttpServletRequest, resp: HttpServletResponse) = { 
     if (!CLIThread.isAlive) { 
      try { 
       CLIThread.start 
      } 
      catch { 
       case _ => resp.getOutputStream().println("Error: thread state is, " + CLIThread.getState) 
      } 
     } 
     resp.getOutputStream().println(CLIThread.pool) 
    } 

    override def destroy(): Unit = { 
     super.destroy() 
     CLIThread.shutdown 
    } 
} 

我們的線程(CLIThread)是scala object擴展Thread類。

CLIThread有2種方法,池&關閉,並且它們都被傳遞給我們的Runnable實現。

CLIRunnable是傳遞給線程構造函數的Runnable實現對象。 (),一個true布爾值(keepAlive)和一個空字符串(_pool)作爲變量。默認情況下,CLIRunnable有一個空ServerSocket(偵聽器),Socket(套接字)&。

run方法:

  1. 分配一個新的ServerSocket到收聽變量。 我使用while循環,布爾型,try-catch塊和隨機函數來分配一個偵聽空端口的serverSocket,否則如果端口被使用,它將拋出異常
  2. 分配接受的套接字從收聽對象(此方法保持線程,直到AA插座連接到聽者,這就是爲什麼我們使用一個線程)
  3. 分配套接字輸入流,以在
  4. 只要的keepAlive爲真檢查是否輸入流不是空的,如果是的話,它用它填充_pool變量。

池方法:

  • 如果變量不爲空(CLIThread開始和插座連接到我們的端口),我們返回_pool字符串和清空。
  • 否則如果上述錯誤但偵聽器不爲空(套接字尚未被接受),我們打印出用戶用於連接到我們的端口的偵聽器的值。
  • 如果上述所有失敗比聽者零化,這意味着線程從來沒有開始,我們打印字符串「聽衆== NULL ......」

關機方法:

  1. 套保持alive設置爲false(釋放從while循環線)
  2. 如果聽者不爲空:
    1. 如果沒有連接到我們的口插座,創建一個連接一個新的插座和關閉這是爲了讓我們的聽衆從循環中釋放出來。
    2. 如果socket不爲null,則關閉它。
    3. 關閉聽者

CLIThread.scala

package com.example 

import java.io.InputStream 
import java.net.ServerSocket 
import java.net.Socket 

object CLIThread extends Thread(CLIRunner) { 
    def pool: String = CLIRunner.pool 
    def shutdown() = CLIRunner.shutdown() 
} 

protected final object CLIRunner extends Runnable { 
    var listener: ServerSocket = null 
    var socket: Socket = null 
    var in: InputStream = null 
    private var keepAlive = true 

    private var _pool = "" 

    def run: Unit = { 
     var ok = false 
     while (!ok) { 
      try { 
       listener = new ServerSocket((math.random * 10000).toInt) 
       ok = true; 
      } 
      catch { 
       case _ => {} 
      } 
     } 
     socket = listener.accept() 
     in = socket.getInputStream 
     while (keepAlive) { 
      while (in.available() > 0) _pool += in.read().toChar 
     } 

    } 
    def pool: String = if (in != null) { 
     val temp = _pool 
     _pool = "" 
     return temp 
    } 
    else if (listener != null) (listener.getInetAddress, listener.getLocalPort).toString 
    else "listener == null..." 

    def shutdown() { 
     keepAlive = false 
     if (listener != null) { 
      if (socket == null) 
       (new Socket(listener.getInetAddress, listener.getLocalPort)).close() 
      if (socket != null) 
       socket.close() 
      listener.close() 
     } 
    } 
} 

CLI.scala

package com.example 

import java.net.Socket 
import java.net.URL 

object CLI extends App { 
    val addr = args(0) // The server address (example.com:8080) 

    val addrUrl = new URL("http://" + addr + "/~cli/addr") 
    var con = addrUrl.openConnection() 
    var in = con.getInputStream() 
    var cliAddr = "" 
    while (in.available() > 0) 
     cliAddr += in.read.toChar 

    val portUrl = new URL("http://" + addr + "/~cli/port") 
    con = portUrl.openConnection() 
    in = con.getInputStream() 
    var cliPort = "" 
    while (in.available() > 0) 
     cliPort += in.read.toChar 

    val socket = new Socket(cliAddr, Integer.valueOf(cliPort)) 

    implicit def stringToByteArray(s: String) = s.toCharArray.map(c => c.toByte) 

    socket.getOutputStream().write("Hellllo from CLI process") 
} 

CliAddr.scala

package org.sdms 

import javax.servlet.http.HttpServlet 
import javax.servlet.http.HttpServletRequest 
import javax.servlet.http.HttpServletResponse 

class CliAddr extends HttpServlet { 
    override def doGet(req: HttpServletRequest, resp: HttpServletResponse) { 
     resp.getWriter.print(CLIRunner.listener.getInetAddress.getHostAddress) 
    } 
} 

CliPort.scala

package com.example 

import javax.servlet.http.HttpServlet 
import javax.servlet.http.HttpServletRequest 
import javax.servlet.http.HttpServletResponse 

class CliPort extends HttpServlet { 
    override def doGet(req: HttpServletRequest, resp: HttpServletResponse) { 
     resp.getWriter.print(CLIRunner.listener.getLocalPort) 
    } 
} 
相關問題