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

📄 client.java

📁 很棒的web服务器源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
     */    protected boolean startConnection(InputStream in, DataOutputStream out) 	throws ClientException    {	boolean   keep      = true ;	long      tstart    = 0 ;	long      tend      = 0 ;	Request   request   = null ;	Reply     reply     = null ;	int       sent      = 0 ;	int       processed = 0;	ClientException err = null;	this.input  = in;	this.output = out;	this.parser = new MimeParser(input, factory);	try {	    running = true;	alive_loop:	    while ( (! interrupted)  && keep ) {		// Get the next available request, and  mark client as used:		try {		    // mark the stream, if some bytes are to be eaten		    if (prev_body_count > 0) {			input.mark(2048);		    }		    if ( processed == 0 ) {			// Always run for the first request, 			// update client's infos			if ((request = getNextRequest()) == null ) 			    break alive_loop;			major = request.getMajorVersion();			minor = request.getMinorVersion();		    } else {			if ( interrupted = idleConnection() )			    break alive_loop;			if ((request = getNextRequest()) == null) 			    break alive_loop;			// the gateway case, the major/minor _may_ change			major = request.getMajorVersion();			minor = request.getMinorVersion();			usedConnection();		    }		} catch (ClientException cex) {		    if (cex.ex != null && 			(cex.ex instanceof HttpParserException)) {			HttpParserException hex = (HttpParserException) cex.ex;			if (!hex.hasRequest()) {			    throw (cex);			}			request = (Request) hex.getRequest();			if ( processed == 0 ) {			    major = request.getMajorVersion();			    minor = request.getMinorVersion();			}			usedConnection();			reply = (Reply) request.makeBadRequestReply();			reply.setContentLength(0);			reply.addConnection("close");			// Inital keep alive check, emit the reply:			keep = false;			sent = emitReply(reply) ;			// Semi-fake log entry			log(request, reply, 0, 0) ;			processed++;			// a bad request is still a request...			reqcount++;			break alive_loop;		    } else if (cex.ex != null && 			(cex.ex instanceof MimeParserException)) {			reply = new Reply(this);			reply.setStatus(HTTP.BAD_REQUEST);			reply.setContentLength(0);			reply.addConnection("close");			keep = false;			sent = emitReply(reply) ;			// Semi-fake log entry			log(request, reply, 0, 0) ;			processed++;			// a bad request is still a request...			reqcount++;			break alive_loop;		    }		    throw (cex);		} catch (Exception genex) {		    if (debug)			genex.printStackTrace();		    // some bytes may have to be eaten		    // abomination, very ugly hack!		    if (genex.getMessage().startsWith("Bad request") && 			(prev_body_count > 0)) {			// check if the error is due to a			usedConnection();			if (debug)			    System.out.println("Error after a body "+					       "request! (Skipping: " +					       prev_body_count+" bytes)");			// now try to eat some data...			input.reset();			byte b[] = new byte[(int)prev_body_count];			prev_body_count -= input.read(b);			prev_body_count -= input.skip(prev_body_count);			break alive_loop;		    }		    throw (genex);		}		// Some traces if required:		if ( debuglog )		    System.out.println(this+": request "+request.getURL());		// Process request, and time it:		tstart  = System.currentTimeMillis() ;		reply   = processRequest (request) ;		tend    = System.currentTimeMillis() ;		// Inital keep alive check, emit the reply:		if ( keep ) 		    keep = tryKeepConnection(request, reply) ;		sent = emitReply(reply) ;		// Second keep alive check:		if (reply.hasContentLength() 		    && (sent >= 0 )		    && (reply.getContentLength() != sent))		    keep = false;		// Log and/or traces:		if ( debuglog )		    System.out.println(this				       + ", cl="+reply.getContentLength()				       + ", size="+sent);		// will be -1 if there is no body		prev_body_count = request.getContentLength();		log(request, reply, sent, tend-tstart) ;		processed++;		// If we can keep alive, and if the client doesn't do		// pipelining, be clever:		// We should compare against 0 here, we use 2 because of a		// well-known client bug, that emits an extra CRLF at the end		// of forms POSTing		// Note we're doing that very last, so that if the socket is 		// closed by peer, we really have *already* done everything		if ( keep  /*&& (in.available() <= 2)*/)		    output.flush() ;		// be clever again... in case of protocol switching,		// we must free everything and let the other client use the		// streams		if (reply.getStatus() == HTTP.SWITCHING) {		    input = null;		    output = null;		    throw new Exception ("Switching");		}		// hack for servlets		if (request.hasState(JigsawHttpServletResponse.STREAM)) {		    try {			PipedInputStream pis;			pis = (PipedInputStream) 			    request.getState(JigsawHttpServletResponse.STREAM);			pis.close();		    } catch (ClassCastException ccex) {			// do nothing		    } catch (IOException pisioex) {			// fail silently also		    }		}	    }	} catch (IOException ex) {	    if ( debug ) {		System.out.println("+++ "+this+" got IOException:");		ex.printStackTrace();	    }	    // Close any stream pending	    try {		InputStream i = null;		if ( reply != null ) {		    if ((i = reply.openStream()) != null)			i.close();		}	    } catch (IOException ioex) {	    }	    err = new ClientException(this, ex);	} catch (ClientException ex) {	    if ( debug ) {		System.out.println("+++ "+this+" got ClientException:");		ex.printStackTrace();	    }	    try {		InputStream i = null;		if ( reply != null ) {		    if ((i = reply.openStream()) != null)			i.close();		}	    } catch (IOException ioex) {	    }	    err = ex;	} catch (Exception ex) {	    if ( debug ) {		System.out.println("+++ "+this+" got exception:");		ex.printStackTrace();	    }	    err = new ClientException(this, ex);	} finally {	    // Absorb incoming data to avoid RST TCP packets:	    if ((err == null) && (request != null)		&& (request.getContentLength() > 0)		&& (reply != null)		&& (reply.getStatus() != HTTP.SWITCHING)		&& (reply.getStatus() / 100 != 2)) {		// The request may have failed...		try {		    InputStream i = request.getInputStream();		    if ( i != null ) {			while (i.available() > 0)			    i.read(buffer, 0, buffer.length);		    }		} catch (Exception ex) {		}	    }	    if ((request != null) && (		request.hasState(JigsawHttpServletResponse.STREAM))) {		try {		    PipedInputStream pis;		    pis = (PipedInputStream) 			request.getState(JigsawHttpServletResponse.STREAM);		    pis.close();		} catch (ClassCastException ccex) {		    // do nothing		} catch (IOException pisioex) {		    // fail silently also		} catch (Exception ex) {		    // be sure not to cause any trouble :)		}	    }	    terminate();	    if (reply == null || (reply.getStatus() != HTTP.SWITCHING)) {		stopConnection();		if (reply != null) {		    try {			reply.openStream().close();		    } catch (Exception roex) {};		}	    }	    if ( err != null )		throw err;	}	return interrupted;    }    /**     * Interrupt the currently handled connection.     * This method will make best effort to interrupt any thread currently     * processing the connection.     * @param now Make sure the thread is interrupted right now if      * <strong>true</strong>, otherwise, just schedule an interruption     * after the current request (if any) has been processed.     */    protected synchronized void interruptConnection(boolean now) {	if ( running ) {	    interrupted = true;	    if ( now )		terminate();	}    }    /**     * Send a 100 HTTP continue message on the currently handled connection.     * This method will take care of creating the appropriate HTTP     * continue reply, and will emit that reply only if the spoken HTTP     * version allows for it.     * @exception IOException If some IO error occured.     */    public int sendContinue() 	throws IOException    {	if (cont)	    return -1;	if ((major > 1) || ((major == 1) && (minor >= 1))) {	    if ( contreply == null )		contreply = new Reply(this, null, major, minor, HTTP.CONTINUE);	    int len = emitReply(contreply);	    output.flush();	    cont = true;	    return len;	}	return -1;    }    /**     * Send a 100 HTTP continue message on the currently handled connection.     * This method will take care of creating the appropriate HTTP     * continue reply, and will emit that reply only if the spoken HTTP     * version allows for it.     * @exception IOException If some IO error occured.     */    public int sendContinue(Reply contReply) 	throws IOException    {	if (contReply == null) {	    return sendContinue();	}	if ((major > 1) || ((major == 1) && (minor >= 1))) {	    int len = emitReply(contReply);	    output.flush();	    cont = true;	    return len;	}	return -1;    }        /**     * Get this client identifier.     * @return An integer identifying uniquely this client's context.     */    public final int getIdentifier() {	return identifier;    }    /**     * Is this client currently <em>running</em> for a connection.     * @return A boolean, <strong>true</strong> if it is,      * <strong>false</strong> otherwise.     */    public final synchronized boolean isRunning() {	return running;    }    /**     * Get the HTTP major version number spoken on the current connection.     * @return The HTTP major version number, or <strong>-1</strong> if that     * client is not running.     */    public final short getMajorVersion() {	return major;    }    /**     * Get the HTTP minor version number spoken on the current connection.     * @return The HTTP minor version number, or <strong>-1</strong> if      * that client is not running.     */    public final short getMinorVersion() {	return minor;    }    /**     * Does this client has an interrupt pending ?     * @return A boolean, <strong>true</strong> if an interrupt is pending,     * <strong>false</strong> otherwise.     */    public final boolean isInterrupted() {	return interrupted;    }    /**     * Get the total number of requests handled within this client context.     * @return An integer giving the number of requests handled.     */    public final int getRequestCount() {	return reqcount;    }    /**     * Get the server context responsible for this client context.     * @return An httpd instance.     */    public final httpd getServer() {	return server;    }    /**     * Emit an error message on behalf of that client.     * @param msg The error message to output.     */    public final void error(String msg) {	server.errlog(this, msg);    }    /**     * Emit a trace on behalf of the given client.     * @param msg The trace to output.     */    public final void trace(String msg) {	server.trace(this, msg);    }    /**     * Log the given HTTP transaction.     * @param request The request that has been processed.     * @param reply The generated reply.     * @param nbytes Number of content bytes sent along with the reply.     * @param duration The processing time for that request in milliseconds.     */    public void log(Request request, Reply reply, int nbytes, long duration) {	server.log (this, request, reply, nbytes, duration) ;    }    /**     * Get this client input stream.     * @return An instance of InputStream, or <strong>null</strong> if the      * client is not handling any connection at that time.     */    public InputStream getInputStream() {	return input;    }    /**     * Get this client output stream.     * @return An instance of OutputStream, or <strong>null</strong> if the     * client is not handling any connection at that time.     */    public DataOutputStream getOutputStream() {	return output;    }    /**     * Get the IP address of the host that runs the client described by this     * context.     * @return An InetAddress instance, or <strong>null</strong> if that client     * is not handling any connection at that given time.     */    abstract public InetAddress getInetAddress();    /**     * Client callback - The client is about to block, getting next request.     * This method is triggered by the client instance itself, before     * reading next request from the input stream provided at     * <code>startConnection</code> time.     * @return A boolean, if <strong>true</strong>, the client will consider     * itself interrupted, and terminate the connection it is current handling.     */    abstract protected boolean idleConnection();    /**     * Client callback - A full request has been received on input stream.     * This method is called by the client itself, before starting processing     * the newly received request. The purpose of this callback is typically     * to mark that client <em>buzy</em>.     */    abstract protected void usedConnection();    /**     * Client callback -  The current connection has been terminated.     * This client has finished processing the connection provided     * at <code>startConnection</code> time, it is now stopped.     */    abstract protected void stopConnection();    /**     * Get the thread powering that client, if any.     * This method is called to kill the client (by interrupting the thread     * used to run it).     * @return A Thread instance, or <strong>null</strong>.     */    abstract protected Thread getThread();    /**     * Initialize this client.     * It is up to this method to initialize:     * <dl>     * <dt>parser<dd>The MimeParser to be used to parse incomminf requests.     * </dl>     * @param server The server responsible for that client.     * @param factory The factory that created this client.     * @param identifier The uniq identifier for this client.     */    protected void initialize(httpd server, int identifier) {	this.server     = server;	this.lenient    = server.isLenient();	this.identifier = identifier;	this.debug      = server.getClientDebug() ;	this.factory    = server.getMimeClientFactory(this);    }}

⌨️ 快捷键说明

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