基于Servlet实现RMI突破防火墙

package com.mypack.web.rmi;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.io.IOException;import java.io.OutputStream;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;import java.net.URL;import java.net.UnknownHostException;import java.rmi.Naming;import java.rmi.RMISecurityManager;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.server.RMIClassLoader;import java.rmi.server.UnicastRemoteObject;import java.util.Hashtable;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * The default RMI socket factory contains several "fallback" mechanisms which * enable an RMI client to communicate with a remote server. When an RMI client * initiates contact with a remote server, it attempts to establish a connection * using each of the following protocols in turn, until one succeeds: *  * 1. Direct TCP connection. 2. Direct HTTP connection. 3. Proxy connection * (SOCKS or HTTP). 4. Connection on port 80 over HTTP to a CGI script. 5. Proxy * HTTP connection to CGI script on port 80. *  * The RMI ServletHandler can be used as replacement for the java-rmi.cgi script * that comes with the Java Development Kit (and is invoked in protocols 4 and 5 * above). The java-rmi.cgi script and the ServletHandler both function as proxy * applications that forward remote calls embedded in HTTP to local RMI servers * which service these calls. The RMI ServletHandler enables RMI to tunnel * remote method calls over HTTP more efficiently than the existing java-rmi.cgi * script. The ServletHandler is only loaded once from the servlet * administration utility. The script, java-rmi.cgi, is executed once every * remote call. *  * The ServletHandler class contains methods for executing as a Java servlet * extension. Because the RMI protocol only makes use of the HTTP post command, * the ServletHandler only supports the doPost * HttpServlet method. The doPost method of this class * interprets a servlet request's query string as a command of the form * "=". These commands are represented by the abstract * interface, RMICommandHandler. Once the doPost * method has parsed the requested command, it calls the execute method on one * of several command handlers in the commands array. *  * The command that actually proxies remote calls is the * ServletForwardCommand. When the execute method is invoked on the * ServletForwardCommand, the command will open a connection on a local port * specified by its param parameter and will proceed to write the * body of the relevant post request into this connection. It is assumed that an * RMI server (e.g. SampleRMIServer) is listening on the local port, "param." * The "forward" command will then read the RMI server's response and send this * information back to the RMI client as the body of the response to the HTTP * post method. *  * Because the ServletHandler uses a local socket to proxy remote calls, the * servlet has the ability to forward remote calls to local RMI objects that * reside in the ServletVM or outside of it. *  * Servlet documentation may be found at the following location: *  * http://jserv.javasoft.com/products/java-server/documentation/ * webserver1.0.2/apidoc/Package-javax.servlet.http.html */public class ServletHandler extends HttpServlet implements Runnable {/* Variables to hold optional configuration properties. *//*** serialVersionUID*/private static final long serialVersionUID = 1L;/** codebase from which this servlet will load remote objects. */protected static String initialServerCodebase = null;/** name of RMI server class to be created in init method */protected static String initialServerClass = null;/** name of RMI server class to be created in init method */protected static String initialServerBindName = null;/*** RMICommandHandler is the abstraction for an object that handles a* particular supported command (for example the "forward" command* "forwards" call information to a remote server on the local machine).* * The command handler is only used by the ServletHandler so the interface* is protected.*/protected interface RMICommandHandler {/*** Return the string form of the command to be recognized in the query* string.*/public String getName();/*** Execute the command with the given string as parameter.*/public void execute(HttpServletRequest req, HttpServletResponse res,String param) throws ServletClientException,ServletServerException, IOException;}/*** List of handlers for supported commands. A new command will be created* for every service request*/private static RMICommandHandler commands[] = new RMICommandHandler[] {new ServletForwardCommand(), new ServletGethostnameCommand(),new ServletPingCommand(), new ServletTryHostnameCommand() };/* construct table mapping command strings to handlers */private static Hashtable commandLookup;static {commandLookup = new Hashtable();for (int i = 0; i super.init(config) may cause a*                servlet exception to be thrown.*/public void init(ServletConfig config) throws ServletException {super.init(config);try {setConfigParameters(config);if (!verifyConfigParameters()) {// dont export any objects.System.err.println("Some optional parameters not set, "+ "remote object not exported; "+ "ServletHandler is runnning.");return;}/** RMI requires that a local security manager be responsible for the* method invocations from remote clients - we need to make sure a* security manager is installed.*/if (System.getSecurityManager() == null) {System.setSecurityManager(new RMISecurityManager());}// create a registry if one is not running already.try {LocateRegistry.createRegistry(1099);} catch (java.rmi.server.ExportException ee) {// registry already exists, we'll just use it.} catch (RemoteException re) {System.err.println(re.getMessage());re.printStackTrace();}/*** Download and create a server object in a thread so we do not* interfere with other servlets. Allow init method to return more* quickly.*/(new Thread(this)).start();System.out.println("RMI Servlet Handler loaded sucessfully.");} catch (Exception e) {System.err.println("Exception thrown in RMI ServletHandler: "+ e.getMessage());e.printStackTrace();}}/*** Create the sample RMI server.*/public void run() {try {UnicastRemoteObject server = createRemoteObjectUsingDownloadedClass();if (server != null) {Naming.rebind(initialServerBindName, server);System.err.println("Remote object created successfully.");}} catch (Exception e) {System.err.println("Exception received while intalling object:");System.err.println(e.getMessage());e.printStackTrace();}}/*** Load and export an initial remote object. The implementation class for* this remote object should not be loaded from the servlet's class path;* instead it should be loaded from a URL location that will be accessible* from a remote client. In the case of this example, that location will be* initialServerCodebase*/UnicastRemoteObject createRemoteObjectUsingDownloadedClass()throws Exception {UnicastRemoteObject server = null;Class serverClass = null;int MAX_RETRY = 5;int retry = 0;int sleep = 2000;while ((retry = MAX_RETRY) {System.err.println("Failed to load remote server "+ " class. Remote object not " + " exported... ");} else {System.err.println("Could not load remote class, "+ "trying again...");try {Thread.sleep(sleep);} catch (InterruptedException ie) {}continue;}}}return server;}/** NOTE: If you are using JDK1.2Beta4 or later, it is recommended that you* provide your servlet with a destroy method that will unexport any remote* objects that your servlet ever exports. As mentioned in the readme file* for this example, it is not possible to unexport remote objects in* JDK1.1.x; there is no method in the RMI 1.1 public API that will perform* this task. To restart remote objects in the servlet VM, you will have to* restart your webserver. In JDK1.2x, the methods to unexport a remote* object are as follows:* * java.rmi.activation.Activatable. unexportObject(Remote obj, boolean* force) java.rmi.server.UnicastRemoteObject. unexportObject(Remote obj,* boolean force)*//*** Execute the command given in the servlet request query string. The string* before the first '=' in the queryString is interpreted as the command* name, and the string after the first '=' is the parameters to the* command.* * @param req*            HTTP servlet request, contains incoming command and arguments* @param res*            HTTP servlet response* @exception ServletException*                and IOException when invoking methods of*                req or res.*/public void doPost(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {try {// Command and parameter for this POST request.String queryString = req.getQueryString();String command, param;int delim = queryString.indexOf("=");if (delim == -1) {command = queryString;param = "";} else {command = queryString.substring(0, delim);param = queryString.substring(delim + 1);}System.out.println("command: " + command);System.out.println("param: " + param);// lookup command to execute on the client's behalfRMICommandHandler handler = (RMICommandHandler) commandLookup.get(command);// execute the commandif (handler != null)try {handler.execute(req, res, param);} catch (ServletClientException e) {returnClientError(res, "client error: " + e.getMessage());e.printStackTrace();} catch (ServletServerException e) {returnServerError(res, "internal server error: "+ e.getMessage());e.printStackTrace();}elsereturnClientError(res, "invalid command: " + command);} catch (Exception e) {returnServerError(res, "internal error: " + e.getMessage());e.printStackTrace();}}/*** Provide more intelligible errors for methods that are likely to be* called. Let unsupported HTTP "do*" methods result in an error generated* by the super class.* * @param req*            http Servlet request, contains incoming command and arguments* * @param res*            http Servlet response* * @exception ServletException*                and IOException when invoking methods of*                req or res.*/public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {returnClientError(res, "GET Operation not supported: "+ "Can only forward POST requests.");}public void doPut(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {returnClientError(res, "PUT Operation not supported: "+ "Can only forward POST requests.");}public String getServletInfo() {return "RMI Call Forwarding Servlet Servlet.
";}/*** Return an HTML error message indicating there was error in the client's* request.* * @param res*            Servlet response object through which message*            will be written to the client which invoked one of this*            servlet's methods.* @param message*            Error message to be written to client.*/private static void returnClientError(HttpServletResponse res,String message) throws IOException {res.sendError(HttpServletResponse.SC_BAD_REQUEST, ""+ "Java RMI Client Error" + ""+ "" + "

Java RMI Client Error

" + message+ "");System.err.println(HttpServletResponse.SC_BAD_REQUEST+ "Java RMI Client Error" + message);}/*** Return an HTML error message indicating an internal error occurred here* on the server.* * @param res*            Servlet response object through which message*            will be written to the servlet client.* @param message*            Error message to be written to servlet client.*/private static void returnServerError(HttpServletResponse res,String message) throws IOException {res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"" + "Java RMI Server Error"+ "" + ""+ "

Java RMI Server Error

" + message+ "");System.err.println(HttpServletResponse.SC_INTERNAL_SERVER_ERROR+ "Java RMI Server Error: " + message);}/*** Retrieve parameters from servlet configuration object.* * @param config*            Standard configuration object for an HTTP servlet.*/protected synchronized void setConfigParameters(ServletConfig config) {try {initialServerCodebase = config.getInitParameter("rmiservlethandler.initialServerCodebase");initialServerClass = config.getInitParameter("rmiservlethandler.initialServerClass");initialServerBindName = config.getInitParameter("rmiservlethandler.initialServerBindName");} catch (Exception e) {System.err.println("");System.err.println("Could not access init parameter:");System.err.println(e.getMessage());e.printStackTrace();}}/*** Ensure that servlet configuration parameters are valid.* * @return true if all relevant configuration parameters are*         valid (i.e. not "") false otherwise.*/protected synchronized boolean verifyConfigParameters() {return ((verifyParameter("rmiservlethandler.initialServerClass ",initialServerClass))&& (verifyParameter("rmiservlethandler.initialServerBindName ",initialServerBindName)) && (verifyParameter("rmiservlethandler.initialServerCodebase",initialServerCodebase)));}/*** Verify that a single parameter is valid.* * @return true if the parameter is valid.*/protected boolean verifyParameter(String parameterName, String parameter) {if ((parameter == null) || (parameter.equals(""))) {System.err.println("optional parameter is invalid and "+ "will not be used:     " + parameterName + " = "+ parameter);return false;} else {System.err.println(parameterName + " " + "valid: " + parameter);}return true;}/** The ServletHandler class is the only object that needs to access the* CommandHandler subclasses, so we write the commands internal to the* servlet handler.*//*** Class that has an execute command to forward request body to local port* on the server and send server reponse back to client.*/protected static class ServletForwardCommand implements RMICommandHandler {public String getName() {return "forward";}/*** Execute the forward command. Forwards data from incoming servlet* request to a port on the local machine. Presumably, an RMI server* will be reading the data that this method sends.* * @param req*            The servlet request.* @param res*            The servlet response.* @param param*            Port to which data will be sent.*/public void execute(HttpServletRequest req, HttpServletResponse res,String param) throws ServletClientException,ServletServerException, IOException {int port;try {port = Integer.parseInt(param);} catch (NumberFormatException e) {throw new ServletClientException("invalid port number: "+ param);}if (port  0xFFFF)throw new ServletClientException("invalid port: " + port);if (port " + "Java RMI Server Hostname Info"+ "" + "");pw.println("

Java RMI Server Hostname Info

");pw.println("

Local host name available to Java VM:

");pw.print("

InetAddress.getLocalHost().getHostName()");try {String localHostName = InetAddress.getLocalHost().getHostName();pw.println(" = " + localHostName);} catch (UnknownHostException e) {pw.println(" threw java.net.UnknownHostException");}pw.println("

Server host information obtained through Servlet "+ "interface from HTTP server:

");pw.println("

SERVER_NAME = " + req.getServerName());pw.println("

SERVER_PORT = " + req.getServerPort());pw.println("

登录后复制

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2553889.html

(0)
上一篇 2025年3月6日 06:51:43
下一篇 2025年3月6日 06:51:56

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论