2012-11-13 52 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) 
    } 
} 
相关问题