📄 socketclient.java
字号:
// SocketClient.java// $Id: SocketClient.java,v 1.24 2004/02/10 13:15:55 ylafon Exp $// (c) COPYRIGHT MIT and INRIA, 1996.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.jigsaw.http.socket ;import java.io.BufferedInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.PrintStream;import java.net.InetAddress;import java.net.Socket;import java.net.SocketException;import org.w3c.jigsaw.http.Client;import org.w3c.jigsaw.http.ClientException;import org.w3c.jigsaw.http.httpd;import org.w3c.tools.resources.ServerInterface;/** * This class implements the object that handles client connections. * One such object exists per open connections at any given time. * <p>The basic architecture is the following: the httpd instance accepts * new connections on its port. When such a connection is accepted a Client * object is requested to the client pool (which can implement what ever * strategy is suitable). Each request is than managed by looking up an * resource and invoking the resource methods corresponding to the request. * @see org.w3c.jigsaw.http.httpd * @see org.w3c.jigsaw.http.Request * @see org.w3c.jigsaw.http.Reply */public class SocketClient extends Client implements Runnable { private static final boolean trace = false; /** * The ClientFactory that created this client. */ private SocketClientFactory pool = null ; /** * The socket currently handled by the client. */ protected Socket socket = null ; /** * Is this client still alive ? */ protected boolean alive = false; /** * The client state for this client, has managed by the SocketClientFactory * @see SocketClientFactory */ SocketClientState state = null; /** * Number of times this client was bound to a connection. */ protected int bindcount = 0; /** * The thread that we have been attached to. */ protected Thread thread = null; /** * Our reusable output buffer. */ protected SocketOutputBuffer bufout = null; /** * Our we idle (waiting for next request ?) */ protected boolean idle = false; /** * are we done? */ protected boolean done = false; /** * Print that client into a String. * @return A String instance. */ public String toString() { if ( thread != null ) return "client-"+state.id+"("+thread.getName()+")"; else return "client-"+state.id; } /** * If this client is allocated a thread, join it. */ public void join() { if (thread != null) { while ( true ) { try { thread.join(); } catch (InterruptedException ex) { } } } } /** * Run for our newly attached connection. * @return A boolean, <strong>true</strong> if the client is to be killed * as decided by its SocketClientFactory creator. */ public void run() { thread = Thread.currentThread(); if ( trace ) System.out.println(this+": powered by "+thread); try { if ( bufout == null ) { // Make sure that buffer is a little smaller then the client // buffer. so writing to it will not copy it int bufsize = getServer().getClientBufferSize() - 1; bufout = new SocketOutputBuffer(socket.getOutputStream() , bufsize); } else { bufout.reuse(socket.getOutputStream()); } startConnection(new BufferedInputStream(socket.getInputStream()) , new DataOutputStream(bufout)); } catch (IOException ex) { if ( debug ) ex.printStackTrace(); } catch (ClientException ex) { if ( debug ) ex.printStackTrace(); // Emit some debugging traces: if ( debug ) { if (ex.ex != null ) ex.ex.printStackTrace() ; else ex.printStackTrace(); } // If output is null, we have killed the connection... if ( alive && ! idle ) { error("caught ClientException: [" + ex.getClass().getName() + "] " + ex.getMessage()) ; } } catch (Exception ex) { if (debug) { System.out.println("unknown exception caught in client run"); ex.printStackTrace(); } } finally { if ( ! pool.clientConnectionFinished(this) ) { pool.clientFinished(this); } thread = null; } } /** * Client implementation - Get the IP address of this client. * @return An InetAddress instance, or <strong>null</strong> if the * client is not currently running. */ public InetAddress getInetAddress () { return (socket != null) ? socket.getInetAddress() : null; } /** * Client implementation - This connection has been stopped. * Make sure the whole socket is closed, and be ready to handle * next connection. */ protected void stopConnection() { if ( trace ) System.out.println(this+": stopConnection."); if ( socket != null ) { try { socket.close(); } catch (Exception ex) { } socket = null;// alive = false;// if (!pool.idleClientRemove(this)) {// pool.clientFinished(this);// } } } /** * Get the thread powering that client. * @return A Thread instance, or <strong>null</strong>. */ protected Thread getThread() { return thread; } /** * Client implementation - The current connection is idle. * The client is about to wait for the next request from the net, mark * it as idle to make it a candidate for persistent connection closing. * @return A boolean, if <strong>true</strong> our client factory wants * us to stop right now, in order to handle some other connection. */ protected boolean idleConnection() { synchronized (state) { if ( trace ) System.out.println(this+": idleConnection."); idle = true; return ! pool.notifyIdle(this); } } /** * Client implementation - The current connection is in use. * A request is about to be processed, mark that connection as used, to * remove it from the idle state. */ protected void usedConnection() { synchronized (state) { if ( trace ) System.out.println(this+": usedConnection."); idle = false; pool.notifyUse(this) ; } } /** * SocketClientFactory interface - Bind the socket to this client. * Binding a socket to a client triggers the processing of the underlying * connection. It is assumed that the client was ready to handle a new * connection before this method was called. * @param socket The socket this client should now handle. */ protected synchronized void bind(Socket socket) { done = false; ServerInterface server = getServer(); if ( trace ) System.out.println(this+": bind."); this.socket = socket ; try { socket.setSoTimeout(server.getRequestTimeOut()); } catch (SocketException ex) { if (trace) ex.printStackTrace(); server.errlog("Unable to set socket timeout!"); } this.idle = false; bindcount++; pool.run(this); } /** * SocketClientFactory interface - Unbind this client. * This client is handling an idle connection, unbind it to make * it free for handling some other more buzy connection. */ protected synchronized void unbind() { if ( trace ) System.out.println(this+": unbind."); interruptConnection(true); } /** * SocketClientFactory interface - Kill this client. * The clean way for our client factory to shut us down unconditionally. * This will free all resources acquired by this client, stop the current * connection processing if needed, and terminate the underlying thread. */ protected synchronized void kill(boolean now) { if ( trace ) System.out.println(this+": kill."); alive = false; interruptConnection(now); } /** * Get the total number of times this client was bound to a socket. * @return An integer, indicatingthe number of bind calls on this client. */ public final int getBindCount() { return bindcount; } /** * Create an empty client, that will be ready to work. * The created client will run and wait for it to be <code>bind</code> * to some socket before proceeding. * @param server The server to which this client is attached. * @param id The client identifier. * @see org.w3c.jigsaw.http.Client * @see org.w3c.jigsaw.http.ClientFactory */ protected SocketClient(httpd server, SocketClientFactory pool, SocketClientState state) { initialize(server, state.id); this.socket = null ; this.pool = pool; this.state = state; this.alive = true; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -