⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxyserver.java

📁 一个用JAVA写的代理服务器的实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
import java.io.*;import java.net.*;import java.util.*;/** * This class uses the Server class to provide a multi-threaded server  * framework for a relatively simple proxy service.  The main() method * starts up the server.  The nested Proxy class implements the  * Server.Service interface and provides the proxy service. **/public class ProxyServer {    /**      * Create a Server object, and add Proxy service objects to it to provide     * proxy service as specified by the command-line arguments.     **/    public static void main(String[] args) {        try {            // Check number of args.  Must be a multiple of 3 and > 0.            if ((args.length == 0) || (args.length % 3 != 0))                throw new IllegalArgumentException("Wrong number of args");	                // Create the Server object            Server s = new Server(null, 12); // log stream, max connections	                // Loop through the arguments parsing (host, remoteport, localport)            // tuples.  For each, create a Proxy, and add it to the server.            int i = 0;            while(i < args.length) {                String host = args[i++];                int remoteport = Integer.parseInt(args[i++]);                int localport = Integer.parseInt(args[i++]);                s.addService(new Proxy(host, remoteport), localport);            }        }        catch (Exception e) {  // Print an error message if anything goes wrong            System.err.println(e);            System.err.println("Usage: java ProxyServer " +			       "<host> <remoteport> <localport> ...");            System.exit(1);        }    }        /**     * This is the class that implements the proxy service.  The serve() method     * will be called when the client has connected.  At that point, it must     * establish a connection to the server, and then transfer bytes back and     * forth between client and server.  For symmetry, this class implements     * two very similar threads as anonymous classes.  One thread copies bytes     * from client to server, and the other copies them from server to client.     * The thread that invoke the serve() method creates and starts these      * threads, then just sits and waits for them to exit.     **/    public static class Proxy implements Server.Service {        String host;        int port;	        /** Remember the host and port we are a proxy for */        public Proxy(String host, int port) {            this.host = host;            this.port = port;        }	        /** The server invokes this method when a client connects. */        public void serve(InputStream in, OutputStream out) {            // These are some sockets we'll use.  They are final so they can            // be used by the anonymous classes defined below.            final InputStream from_client = in;            final OutputStream to_client = out;            final InputStream from_server;            final OutputStream to_server;            // Try to establish a connection to the specified server and port            // and get sockets to talk to it.  Tell our client if we fail.            final Socket server;            try {                 server = new Socket(host, port);                 from_server = server.getInputStream();                to_server = server.getOutputStream();            }            catch (Exception e) {                PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));                pw.print("Proxy server could not connect to " + host +			 ":" + port + "\n");                pw.flush();                pw.close();                try { in.close(); } catch (IOException ex) {}                return;            }	                // Create an array to hold two Threads.  It is declared final so            // that it can be used by the anonymous classes below.  We use an            // array instead of two variables because given the structure of            // this program two variables would not work if declared final.            final Thread[] threads = new Thread[2];	                // Define and create a thread to copy bytes from client to server            Thread c2s = new Thread() {		    public void run() {			// Copy bytes 'till EOF from client			byte[] buffer = new byte[2048];			int bytes_read;			try {			    while((bytes_read=from_client.read(buffer))!=-1) {				to_server.write(buffer, 0, bytes_read);				to_server.flush();			    }			}			catch (IOException e) {}			finally {			    // When the thread is done			    try {				server.close();     // close the server socket				to_client.close();  // and the client streams				from_client.close();			    }			    catch (IOException e) {}			}		    }		};            // Define and create a thread to copy bytes from server to client.	    // This thread works just like the one above.            Thread s2c = new Thread() {		    public void run() {			byte[] buffer = new byte[2048];			int bytes_read;			try {			    while((bytes_read=from_server.read(buffer))!=-1) {				to_client.write(buffer, 0, bytes_read);				to_client.flush();			    }			}			catch (IOException e) {}			finally {			    try {				server.close(); // close down 				to_client.close();				from_client.close();			    } catch (IOException e) {}			}		    }		};	                // Store the threads into the final threads[] array, so that the             // anonymous classes can refer to each other.            threads[0] = c2s; threads[1] = s2c;	                // start the threads            c2s.start(); s2c.start();	                // Wait for them to exit            try { c2s.join(); s2c.join(); } catch (InterruptedException e) {}        }    }}/** * This class is a generic framework for a flexible, multi-threaded server. * It listens on any number of specified ports, and, when it receives a  * connection on a port, passes input and output streams to a specified Service * object which provides the actual service.  It can limit the number of * concurrent connections, and logs activity to a specified stream. **/class Server {       // This is the state for the server    Map services;                   // Hashtable mapping ports to Listeners    Set connections;                // The set of current connections    int maxConnections;             // The concurrent connection limit    ThreadGroup threadGroup;        // The threadgroup for all our threads    PrintWriter logStream;          // Where we send our logging output to    /**     * This is the Server() constructor.  It must be passed a stream      * to send log output to (may be null), and the limit on the number of     * concurrent connections.       **/    public Server(OutputStream logStream, int maxConnections) {         setLogStream(logStream);        log("Starting server");        threadGroup = new ThreadGroup(Server.class.getName());	this.maxConnections = maxConnections;        services = new HashMap();	connections = new HashSet(maxConnections);    }        /**      * A public method to set the current logging stream.  Pass null     * to turn logging off     **/    public synchronized void setLogStream(OutputStream out) {        if (out != null) logStream = new PrintWriter(out);        else logStream = null;    }    /** Write the specified string to the log */    protected synchronized void log(String s) {         if (logStream != null) {            logStream.println("[" + new Date() + "] " + s);            logStream.flush();        }    }    /** Write the specified object to the log */    protected void log(Object o) { log(o.toString()); }        /**     * This method makes the server start providing a new service.     * It runs the specified Service object on the specified port.     **/    public synchronized void addService(Service service, int port)	throws IOException    {        Integer key = new Integer(port);  // the hashtable key        // Check whether a service is already on that port        if (services.get(key) != null)             throw new IllegalArgumentException("Port " + port +					       " already in use.");        // Create a Listener object to listen for connections on the port        Listener listener = new Listener(threadGroup, port, service);        // Store it in the hashtable        services.put(key, listener);        // Log it        log("Starting service " + service.getClass().getName() + 	    " on port " + port);        // Start the listener running.        listener.start();    }        /**     * This method makes the server stop providing a service on a port.     * It does not terminate any pending connections to that service, merely     * causes the server to stop accepting new connections     **/    public synchronized void removeService(int port) {        Integer key = new Integer(port);  // hashtable key        // Look up the Listener object for the port in the hashtable        final Listener listener = (Listener) services.get(key);        if (listener == null) return;        // Ask the listener to stop        listener.pleaseStop();        // Remove it from the hashtable        services.remove(key);        // And log it.        log("Stopping service " + listener.service.getClass().getName() + 	    " on port " + port);    }        /**      * This nested Thread subclass is a "listener".  It listens for     * connections on a specified port (using a ServerSocket) and when it gets     * a connection request, it calls the servers addConnection() method to     * accept (or reject) the connection.  There is one Listener for each     * Service being provided by the Server.     **/    public class Listener extends Thread {        ServerSocket listen_socket;    // The socket to listen for connections        int port;                      // The port we're listening on        Service service;               // The service to provide on that port        volatile boolean stop = false; // Whether we've been asked to stop        /**	 * The Listener constructor creates a thread for itself in the	 * threadgroup.  It creates a ServerSocket to listen for connections	 * on the specified port.  It arranges for the ServerSocket to be	 * interruptible, so that services can be removed from the server.	 **/        public Listener(ThreadGroup group, int port, Service service) 	    throws IOException	{            super(group, "Listener:" + port);                  listen_socket = new ServerSocket(port);            // give it a non-zero timeout so accept() can be interrupted            listen_socket.setSoTimeout(600000);            this.port = port;            this.service = service;        }        /** 	 * This is the polite way to get a Listener to stop accepting	 * connections	 ***/        public void pleaseStop() {            this.stop = true;              // Set the stop flag            this.interrupt();              // Stop blocking in accept()	    try { listen_socket.close(); } // Stop listening.	    catch(IOException e) {}        }                /**	 * A Listener is a Thread, and this is its body.	 * Wait for connection requests, accept them, and pass the socket on	 * to the addConnection method of the server.	 **/        public void run() {            while(!stop) {      // loop until we're asked to stop.                try {                    Socket client = listen_socket.accept();                    addConnection(client, service);                }                 catch (InterruptedIOException e) {}                 catch (IOException e) {log(e);}            }        }    }	    /**     * This is the method that Listener objects call when they accept a     * connection from a client.  It either creates a Connection object      * for the connection and adds it to the list of current connections,     * or, if the limit on connections has been reached, it closes the      * connection.      **/    protected synchronized void addConnection(Socket s, Service service) {	// If the connection limit has been reached	if (connections.size() >= maxConnections) {	    try {		// Then tell the client it is being rejected.		PrintWriter out = new PrintWriter(s.getOutputStream());		out.print("Connection refused; " +			  "the server is busy; please try again later.\n");		out.flush();		// And close the connection to the rejected client.		s.close();		// And log it, of course		log("Connection refused to " +		    s.getInetAddress().getHostAddress() +		    ":" + s.getPort() + ": max connections reached.");	    } catch (IOException e) {log(e);}	}	else {  // Otherwise, if the limit has not been reached	    // Create a Connection thread to handle this connection	    Connection c = new Connection(s, service);	    // Add it to the list of current connections	    connections.add(c);	    // Log this new connection	    log("Connected to " + s.getInetAddress().getHostAddress() +		":" + s.getPort() + " on port " + s.getLocalPort() +

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -