A simple web server (build 2002-8-20)

zhaozj2021-02-08  236

Below is the source code, if you need a Class file that you need to package, please contact you: hcc4hcc@163.com (Note: Import in the program, there is no listing here) readme.txt ========== ======================================================================================================================================================================================================================================================================================= Speed, but not obvious; support breakpoint resume, support multi-thread download, but does not support IE breakpoint resume (not know why); currently testing on a FlashGet. 0.8 version update: Increase the thread pool; Class: WebserverLogger; optimize part of the code; add a custom log file name; increase the number of threads MAX and MIN in the custom thread pool; increase the number of customizable Size; (increasing the most important setting of download speed, recommended 128-256KB) increase timeout setting; (currently 5 seconds) Remove the bug found in the page (whose reason: It turned out to be two times in each thread () .: p); Fixed a format error in the HTTP protocol to correct the compatibility between the HTTP protocol and FlashGet, FlashGet can be downloaded normally (why: flashget establishes a socket connection with this server, no immediately Data, there is a short latency because this server has been optimized, and the response is very fast, and there is no timeout, so it is considered that the flashget is not connected, so it is cut off. Note: IE download and Netants have no problem.); Changed nearly 1/2 code. All Features: You can customize the listening port; you can customize whether the directory list is listed; you can customize the server name; you can customize the index file name; do not restart the server, change the parameter file (WebServer.ini) to take effect immediately; Except for high-speed, optimized IO processing, speed is not Apache; -> need JAR packaging files to contact: After packaging (JAR package), easy to use, only 2 files: one JAR file and a parameter file; (except generated log file) log record detailed, including client IP addresses, port numbers, machine names, and thread IDs that connect services; thread safety, consumption is not large.

Webserver.java =============================================== = / ******************* * * Simple web server * * @Author: hcc * * @version: 0.85 build 2002-8-20 * ***** ************** / package hcc; import java.io. *; import java.Net. *; import java.util. *; import java.text. *; public class webserver { / ** * WebServer constructor * / public webserver () {more serious error, print to the console, not log boolean existers = false; read console command BUFFEREDReader readcmd = null; SimpleWebServerManager SWSM = NULL; try { SWSM = SimpleWebServerManager.getInstance (); system.out.println ("/ n :) === Simple Web Server ==="); system.out.println (":) Running on port" swsm.getport () "..."); readcmd = new bufferedreader (new inputs); string cmd = null; system.out.print ("/ nsimple web server command>); receive input command while ((cmd = Readcmd.readLine ())! = null) {IF (cmd.equals ("shutdown") || cmd.equals ("sd")) Break; Else IF (cmd.equals ("?") || cmd. Equals ("Help")) System.out.Println ("/ Nsyntax: /" shutdown / "--- Shutdown Simple Web Server / N "); else system.out.println (" / n :( Bad command! / n / "); system.out.print (" SIMPLE Web Server); SIMPLE Web Server Command> ");} system.out.print (" / n :) Shutdown Simple Web Server ...); swsm.interrupt (); SWSM.DESTROY (); System.Out.println ("OK"); (Exception E) {EXISTERROR = true; E.PrintStackTrace ();

FinalLy {Try {readcmd.close ();} Catch (Exception Ignored) {} ​​readcmd = NULL; if (Existerror) System.exit (1); else system.exit (0);}} public static void main (String [] args) {new webserver ();}} simpleWebserver.java =================================== ======== Package hcc; import java.io. *; import java.net. *; import java.util. *; import java.text. *; import edu.oswego.cs.dl.util. concurrent.ConcurrentReaderHashMap; public class SimpleWebServer extends Thread {current version number of private static final String vERSION = "0.85"; and the like check whether the parameter debug public static boolean debug = false; Encode private URL of static String Encode = null; ID private String ID; private Socket socket = null; server IP private String serverIP = null; server name private String serverName = null; index file name, press lookup private static String order from the first to [] indexFiles = null; root path private static String Rootpath = NULL; Removal Private String Separator = NULL in the operating system of the server; whether to list the file private static boolean allowlistfiles = true; customer ip private string clientIP = null; client port private int clientPort; client host name private String clientName = null; Date format private static HTTP protocol SimpleDateFormat dateFormat = null; Output buffer size (byte) private int outputBuffer = 256 * 1024; customer request information private String requestStr = null; store configuration parameters private static ConcurrentReaderHashMap properties = null; // read all the threads can be complicated, but HashMap socket can only be written synchronously read buffer public static final int rEAD_BUFFER_SIZE = 1 * 1024; log information types Private static final int error = 0;

Private static final int warning = 1; private static final int debu = 2; private static final int debug = 3; // Constant parameters: The error page stored in the webserver.ini file is also used to identify the error type private statin NOT_FOUND = "NOT_FOUND_404"; private static final String BAD_REQUEST = "BAD_REQUEST_400"; request error private static final String INTERNAL_ERROR = "INTERNAL_ERROR_500"; internal server error private static final String FORBIDDEN = "FORBIDDEN_403"; Forbidden / default error page private static Final String Default_not_found = " File Not Found! </ Title> <body bgcolor = /" # fffff / "> <h1> error 404: <br> File Not Found! </ h1> <br> <br> <hr> <center> <font face = / "verdana /"> Simple Web Server " Version " <B> by HCC </ B> </ font> </ center> </ body> </ html > "; private static final string default_bad_request =" <html> <title> Bad Request! </ title> <body bgcolor = / "# ffffff /"> <h1> error 400: <br> Bad Request! </ h1> <br> <br> <hr> <center> <font face = / "Verdana /"> Simple Web Server " VERSION " <b> by hcc </ b> </ font> </ center> </ body> </ html> "; private static final string default_in TERNAL_ERROR = "! <Html> <title> Internal Error </ title> <body bgcolor = /" # FFFFFF / "> <h1> ERROR 500: <br> Internal Error </ h1> <br> <br> <! HR> <center> <font face = / "verdana /"> Simple Web Server " Version " <B> by HCC </ b> </ font> <</p> <p>/ center> </ body> </ html> "; private static final string default_forbidden =" <html> <title> forbidden! </ title> <body bgcolor = / "# fffff /"> <h1> error 403: < br> Forbidden! </ h1> <br> <br> <hr> <center> <font face = / "Verdana /"> Simple Web Server " VERSION " <b> by hcc </ b> </ font> </ center> </ body> </ html> "; log private WebServerLogger log = null; socket of the I / O stream private PrintStream out = null; private BufferedReader in = null; private BufferedInputStream fin reading documents with = null; / ** constructor * / public SimpleWebServer (Socket socket, String ID, ConcurrentReaderHashMap p) throws NullPointerException, IOException {debug == true, debug if (debug) {if (ID == null) throw new NullPointerException ( "parameter error! ID is NULL (Property Error: / "ID /" is NULL) "); if (socket == null) throw new nullpointRexception (" Parameter error! Socket is null (property error: / "socket /" is null) ") } this.id = ID; this.socket = socket; proties = p; index files indexfiles = (string []) Properties.get ("index"); root path rootpath = (string) Properties.get ("root" Server IP Server IP = (String) Properties.get ("Serverip"); server name servername = (string) Properties.get ("ServerName"); if (ServerName == Null || ServerName.Equals (")) ServerName = ServerIP; The server's restroom SEPARATOR = (String) Properties.get ("separator"); whether the current directory file String LF = (String) Properties.get ("listfiles"); allowListFiles = lf.EqualsignoreCase YES ");</p> <p>Date format DateFormat = ("DateFormat") in the HTTP Protocol; Encode Encode = (String) Properties.get ("Encode"); log this.log = (WebServerLogger) Properties.get (" "); Output cache size (Byte) this.outputbuffer = integer.parseint (" OutputBuffer ") * 1024; this.clientip = this.socket.get Add (); client (); gethostaddress (); client IP this.clientPort = this.socket.getPort (); client port this.clientName = this.socket.getInetAddress () getHostName ();. client name this.in = new BufferedReader (new InputStreamReader (this.socket.getInputStream () )); this.out = new printStream (new bufferedoutputstream (this.socket.getOutputStream ()), true);} / ******************** Private MOTHED Start: ****************************** * Record log * * @Param MessageType log type: error, warning, info * information * / private void doLog @param message to be recorded (int messageType, String message) {StringBuffer messTmp = new StringBuffer (); messTmp.append ( "(ConnectionID:" this.ID ")"); messTmp.append ( THIS.CLIENTIP ":" " this.clientname ") ")") "); messtmp.append (message); Switch (MessageType) {case error: this.log.error (MesStmp.Tostring ()); break; case warning: this. Log.warning (Mestring ()); Break; Case Info: this.log.info (Mestring ()); Break; Case Debug: this.log.debug (Mestring (); BREAK;} } / ** * Send HTTP header information, add the Enter of the HTTP protocol ("/ r / n") * / private void println (String s) {this.out.print (S "/ R / N ");} / ** * Send the carriage return commission (" / r / n ") * / private void println () {this.Print (" / r / n ");} / ** * Read the request information header,</p> <p>To "/ r / n / r / n" End * * @return request information network * @exception IOException reasons * / private String getRequestString () throws IOException {this.doLog (DEBUG, "getRequestString () requestStr =" requestStr) StringBuffer SB = New StringBuffer (500); char [] cbuf = new char []b = new char [4]; char c = 0; int crlfpos = 0; int currpos = 0; current location int Maxpos = 0; maximum location while {if (currpos == maxpos) {maxpos = this.in.read (CBUF, 0, READ_BUFFER_SIZE); if (MAXPOS == -1) Break; currpos = 0; SB. Append (CBUF, 0, MAXPOS);} C = CBUF [Currpos ]; if (c == '/ r') {Try {CRLF [CRLFPOS ] = C;} catch (arrayindexoutofboundsexception e) {crlfpos - = 2; } else if (c == '/ n') {try {crlf [CRLFPOS ] = C; arrayindexoutofboundsexception e) {CRLFPOS - = 2;} if (CRLF [0] == '/ r' && CRLF [ 1] == '/ n' && CRLF [2] == '/ r' && crlf [3] == '/ n') Break;} else {crlfpos = 0; CRLF [0] = 0; CRLF [1 ] = 0; CRLF [2] = 0; CRLF [3] = 0;}} / ** readline () mode: string str = this.in.readline (); while (str! = Null&&! Str.equals ( "")) {sb.append (STR "/ r / n"); str = this.in.readline ();} * / return sb.substring (0, sb.indexof ("/ r / n / r / n ") 4);}-speed output stream private void fastOutput (InputStream in, PrintStream out, int bufferSize) throws IOException {PrintStream with a byte as a byte write is very slow, so the use of the local cache speed int buffSize = bufferSize ; if (buffsize <0) buffsize = 256 * 1024; default 256kb byte [] buffer = new byte [buffsize]; int b; while ((b = in.read (buffer))! =</p> <p>-1) {if (out.checkerror ()) {this.dolog (info, "transfer is aborted!"); Break;} else out.write (buffer, 0, b);} buffer = null;} high speed Output flow (to achieve the 206 response - HTTP) private void fastOutput (InputStream in, PrintStream out, int bufferSize, long skipBytes) throws IOException {in.skip (skipBytes); this.fastOutput (in, out, bufferSize);} / **************************************************************************************************************************** ***************************** Protected method start: *********************** *** / / ** * perform GET * * @exception IOException network cause * / protected void doGet () throws IOException {this.doLog (DEBUG, "doGet (start) requestStr =" requestStr); sendFile (getRequestFileName () ); this.dolog (debug, "doget) RequestStr =" requeststr);} / ** Verify that the request file path is legal (whether it exceeds rootpath range) * * @Param path relative path * @Exception oException file read error * / protected boolean isAllowAccess (String path) throws IOException {this.doLog (DEBUG, "isAllowAccess () requestStr =" requestStr); return getAbsolutePath (path) .indexOf (new File (rootPath) .getCanonicalPath ())> = 0;} / ** send file * / P rotected void sendFile (String fileName) throws IOException {this.doLog (DEBUG, "sendFile (start) requestStr =" requestStr); if {beyond rootPath range, does not allow access this.doLog (INFO, (isAllowAccess (fileName)!) getRequestMethod () "" fileName "failed:! 403 Forbidden"); write log sendError (FORBIDDEN);} else {String fileFullPath = getAbsolutePath (fileName); if (fileName == null || fileName.charAt (0)! = '/') Request file name NULL or the first character is not "/" {this.dolog (info, getRequestMethod () " filename " failed: 400 bad request! "); Write log senderror (Bad_Request) ;</p> <p>} If FileName is "/" end or filename as a directory, the file Else IF in IndexFiles is listed in IndexFiles (filename.endswith). Isdirectory ()) {this.dolog (INFO, GetRequestMethod () " filename); write log if (filename.endswith (" / ")) SendIndexFile (FileName.Substring (0, filename.lastIndexof ('/')))); else sendIndexfile (filename) } else {file f = new file (filefullpath); string key = "Range: Bytes ="; int pos = this.RequestStr.tolowerCase (). Indexof (key); if (pOS> 0) breakpoint resume { String startpos = this.requeststr.substring (POS key.Length (), this.RequestStr.indexof ("-", pOS)); try {long start = long.parselong (startpos); try {this.fin = new BufferedInputStream (new FileInputStream (f)); int finLength = this.fin.available (); if finLength <0, corresponding to the file is not found, it is still thrown FileNotFoundException if (finLength <0) throw new FileNotFoundException (); else { This.dolog (Info, getRequestMethod () "" FileName "Renewal!"); Write log this.println ("http / 1.0 206 partial content"); this.println ("Server: Simple Web Server"); this.println ("Connection: Close"); T His.Println ("Date:" DateFormat (new date ())); this.println ("Content-Type:" f.tourl (). OpenConnection (). getContentType ()); this.println "Last-Modified:" DateFormat.Format (New Date (f.lastmodified ())))))))))))))))); this.Println ("Content-Length:" ("Content-length"); this.println ("Content -Range: BYTES " Start " - " FinLength " / " FinLength); this.println (); fastoutput (this.fin, this.out, this.outputbuffer, start);</p> <p>}} Catch (FileNotFoundException e) {this.doLog (INFO, getRequestMethod () "" fileName "failed:! 404 Not Found"); write log sendError (NOT_FOUND);}} catch (NumberFormatException nfe) {this.doLog (INFO, getRequestMethod () "" fileName "failed:! 400 Bad Request"); write log sendError (BAD_REQUEST);}} end if HTTP else {try {this.fin = new BufferedInputStream (new FileInputStream ( f)); int finLength = this.fin.available (); if FinLength <0, it is equivalent to the file is not found, so still throwing FileNotFoundException if (FinLength <0) throw new filenotfoundexception (); else {this.dolog (info GetRequestMethod () " filename); write log this.println (" http / 1.0 200 ok "); this.println (" Server: Simple Web Server "); this.println (" Connection: Close "); THIS.PRINTLN ("Date:" DateFormat.Format (New Date ())); this.println ("Content-Type:" f.tourl (). OpenConnection (); getContentType ()); this.println "Accept-ranges: Bytes"); this.println ("Last-Modified:" DateFormat.Format (new date (f.lastmodified ()))))))))))); this.println ("Content-Length:" FinLength; this.printl n (); fastoutput (this.fin, this.out, this.outputbuff);}} catch (filenotfoundexcection e) {this.dolog (info, getRequestMethod () " filename " Failed: 404 Not Found! ") Write log senderror (not_found);}}}} this.dolog (debug, "sendfile (end) requeststr =" requeststr);} / ** Find and send files in the IndexFiles list * @Param Dir directory relative path ( There is no "/") * / protected void sendindexfile (String Dir) throws ioException {this.dolog (debug, "SendIndexFile (start) RequestStr =" RequestStr); string index = null;</p> <p>The absolute path of DIR String path = getabsolutePath (DIR); retrieves the first INDEX file for the first existing index file for (I ) {if (new file (path file) {if (I ) {if (I ) {if (I ) {if (i ) {if (I ) {if (I ) {if (I ) {if (I ) {if (I ) {IF (NEW File) {IF (NEW File) {IF (I File) {IF (NEW File) {IF (NEW File) {IF (NEW File). Separator indexfiles [i]). EXISTS ()) {index = path file.separator indexfiles [i]; break;}} if (index! = null) {TRY {this.fin = new bufferedInputStream (New FileInputStream INDEX); int finLength = this.fin.available (); if (FinLEngth> = 0) {this.dolog (info, getRequestMethod () " DIR " / " index.substring (INDEX.lastIndexof .SEPARATOR) 1) "OK: 200"); write log this.println ("http / 1.0 200 ok"); this.println ("Server: Simple Web Server"); this.println ("Date:" DATEFORMAT.FORMAT (New Date ()); this.println ("Content-Type: Text / HTML); this.println (" Accept-Ranges: Bytes "); this.println (" Last-Modified: " DateFormat.Format (new file (index) .lastmodified ())))))))))))); this.Println ("Content-length:" FinLength; this.println (); fastoutput (this.fin, this.out , this.outputbuffer;}} catch (filenotfoundexception e) {this.dolog (info, getRequestMethod () " DIR " / " indee X.SubString (File.Separator) 1) "Failed: 404 Not Found!"); Write LOG If allowlistfiles lists all files (allowlistfiles) listfiles (dir) in the file directory; Else senderror (not_found);}} elwlistfiles lists all files Listfiles (Dir) ListFiles (Dir) under the file directory; excitation (not_found);} this.dolog (debug, "SendIndexFile (End) RequestStr = " RequestSTS;} / ** Send Error * / protected void senderror (String ErrorType) throws ioException {this.dolog (debug," Senderror () requeststr = " requeststr);</p> <p>NOT_FOUND IF (NOTTYPE.EQUALS) {this.println ("HTTP / 1.0 404 Not Found"); this.println ("Server: Simple Web Server"); this.println ("Date:" DateFormat.Format (New Date ()); this.println ("Content-Type: Text / HTML"); try {string errorfile = (string) Properties.get (not_found); if (errorfile == null) throw new filenotfoundexception () ; else {this.fin = new BufferedInputStream (new FileInputStream (errorFile)); int finLength = this.fin.available (); if finLength is 0, corresponding to the file is not found, it is still thrown FileNotFoundException if (finLength <= 0 Throw new filenotfoundexception (); else {this.println ("Accept-ranges: Bytes"); this.println ("Content-length:" FinLENGTH); this.println (); fastoutput (this.fin, this. out, this.outputBuffer);}}} catch (FileNotFoundException e) {this.println ( "Content-length:" default_NOT_FOUND.getBytes () length); this.println (); this.println (default_NOT_FOUND);}. } BAD_REQUEST ELSE IF (ERRORTYPE.EQUALS (Bad_Request)) {this.println ("HTTP / 1.0 400 Bad Request"); this.println ("Server: SIM) PLE Web Server "); this.println (" Date: " DateFormat (New Date ())); this.println (" Content-Type: Text / HTML "); try {string errorfile = (string) Properties .get (BAD_REQUEST); if (errorFile == null) throw new FileNotFoundException (); else {this.fin = new BufferedInputStream (new FileInputStream (errorFile)); int finLength = this.fin.available (); if 0 is finLength It is equivalent to the file being found, so I still throw FileNotFoundException if (FinLength <= 0) throw new filenotfoundexception (); else {this.println ("Accept-ranges: Bytes"); this.println ("Content-length:" FINLENGTH);</p> <p>This.println (); fastoutput (this.fin, this.out, this.outputbuffer);}}} catch (filenotfoundexcection e) {this.println ("Content-length:" default_bad_request.getbytes (). Length); THIS.PRINTLN (); this.println (default_bad_request);}}}}}}} forbidden else if (ErrorType.equals (forbidden)) {this.println ("HTTP / 1.0 400 Bad Request"); this.println ("Server: Simple Web) Server "); this.println (" Date: " DateFormat (new date ())); this.println (" Content-Type: Text / Html "); try {string errorfile = (string) Properties.get (FORBIDDEN); if (errorFile == null) throw new FileNotFoundException (); else {this.fin = new BufferedInputStream (new FileInputStream (errorFile)); int finLength = this.fin.available (); if finLength is 0, quite Not found in the file, so I still throw FILENOTFOUNDEXCEPTION IF (FINLENGTH <= 0) throw new filenotfoundexception (); else {this.println ("Accept-ranges: Bytes"); this.println ("Content-length:" FinLENGTH ); this.println (); fastoutput (this.fin, this.out, this.outputbuffer);}}} catch (filenotfoundexcection e) {THI S.println ("Content-Length:" default_forbidden.getbytes (). Length); this.println (); this.println (default_forbidden);}}} / ************ ************ protected method end ********************************************************************************* ************** PUBLIC METHOD Start: ************************************************************************************** String getRequestMessage () {return this.requestStr;} / ** return request method, such as GET POST HEAD OPTIONS PUT DELETE TRACE etc. * / public String getRequestMethod () {this.doLog (DEBUG, "getRequestMethod () requestStr =" requestStr ); try {return this.requeststr.substring (0, this.RequestStr.Indexof ('')). TouPpercase ();</p> <p>} Catch (Exception e) {return null;}} / ** returns the requested file name, such as: "/ index.html" (already decode) * / public String getRequestFileName () throws UnsupportedEncodingException {this.doLog (DEBUG, "getRequestFileName () REQUESTSTR = " RequestStr); try {string s = this.requeststr.substring (this.RequestStr.indexof ('') 1, this.RequestStr.Indexof ('/ n')); if included? The parameters only take the file name IF in front of the number (S.Indexof ('?') <0) s = s.substring (0, s.lastIndexof (')); else s = s.substring (0, S.indexOf ('?')); return urldecoder.decode (s, eNCode);} catch (exception e) {return null;}} / ** resolution enlightenment = Value pair behind the URL path (Decode ) * / public String getQueryString () throws UnsupportedEncodingException {this.doLog (DEBUG, "getQueryString () requestStr =" requestStr); try {String s = this.requestStr.substring (this.requestStr.indexOf ( '') 1 This.RequestStr.indexOf ('/ n')); if there is no key = value pair behind the URL (S.IndexOf ('?') <0) Return Null; Else S = S.SUBSTRING (S. IndexOf ('?') 1, S.lastIndexOf ('')); Return Urldecoder.Decode (S, Encode);} catch (Exception E) {Return NUL l;}} / ** parsed path on the local machine complete path * / public String getAbsolutePath (String path) throws IOException {this.doLog (DEBUG, "getAbsolutePath () requestStr =" requestStr); return new File (rootPath path.replace ('/', file.separator). getcanonicalPath ();} / ** list the * @Param D directory relative path (end without "/") * / public void Listfiles (String d) throws ioException {this.dolog (debug, "listfiles (start) RequestStr = RequestStr); if (! isllowaccess (d)) {beyond the rootpath range, not allowing access to senderror (Forbidden);</p> <p>} else {file dir = new file (GetabsolutePath (D)); if (Dir.exists ()) {this.dolog (info, getRequestMethod () " D " / List Dirctory Files! "); Write Log String [] filelist = dir.list (); stringbuffer sb = new stringbuffer ("<html>" separator <title> Directory List </ title> " sepant " <body bgcolor = / "# ffffff /"> " SEPARATOR); sb.append ("<font face = /" TIMES New Roman / "> <h1> http: //"); SB.Append (ServerName); string porttmp = (string) Properties.get ("port" If the port is 80, the port number if (! Porttmp.equals ("80")) sb.append (":" porttmp); if (d.Length () == 0) {sb.append ( "/"); sb.append (d);} else {sb.append (d); sb.append ( "/");} sb.append ( "</ h1> </ font> <br> < hr> <br> <br> " separator); parent directory link.</p> <p>If D.Length () == 0 Description is already a root directory, no upper-level directory link IF (D.Length ()! = 0) sb.append ("<- <a href = /" " D .substring (0, d.lastIndexOf ( "/") 1) "/"> Parent Directory </a> <br> <br> " separator); for (int i = 0; i <fileList.length ; i ) {IF ((New file (GetBsolutePath (D "/" fileList [i]))). Isdirectory ()) sb.append ("Directory - <a href = /" fileList [i] "//"> " fileList [i] " / </a> <br> <br> " separator); else sb.append (" <a href = / "" fileList [i] "/ ">" fileList [i] "</a> <br> <br>" separator);} sb.append ( "<br> <hr> <center> <font face = /" Verdana / "> Simple Web Server " Version " <B> by HCC </ b> </ font> </ center> " Separator " </ body> " Separator " </ html> "); string STEMP = Sb.Tostring ); this.Println ("HTTP / 1.0 200 OK"); this.println ("Server: Simple Web Server"); this.println ("Date:" DateFormat (New Date ())); this. Println ("Content-Type: Text / HTML); this.println (" Content-Length: " STEMP.GETBYTES (). Length); this.println (); this.println (STEMP);} else senderror NOT_FOUND);} this.dolog (debug, "listfiles (end) requeststr =" requeststr);} / ** Return only One sign * / public string getId () {return this.id;} / ** Equals () * / public boolean equals (object o) {if (o instanceof simplebserver) Return this.Equals ((SimpleWebserver) O ) .GETID ()); else returnaf false;</p> <p>} / ** hashcode () * / public int 6code () {return this.id.hashcode ();} / ** All run code * / public void run () {try {ix (! @Trupted ()) If it is not interrupted, execute {this.RequestStr = getRequestString (); string rm = getRequestMethod (); this.dolog (debug, "Run (start) requeststr = requeststr); if (rm! = Null) The request is null, then do not do any response (such as the client has disconnected or refresh) {Perform GET request if (RM.Equals ("get")) doget (); else senderror (Bad_Request); this.rewFlush ( );}}} Catch (Exception E) {Print error message to the log file If it is InterruptedException, what doesn't do, because WebServer Shutdown This thread is interrupted if (! (e instanceof interfacedexception) this.log.ERROR e);} finally {destroy ();} this.dolog (debug, "run (end) requeststr =" requeststr);} / ** design: Turn off all I / O streams defined in Webserver Class * / Public void destroy () {THIS.OUT.CLOSE ();} catch (exception ignored) {} ​​OUT does not throw oException this.out = null; try {this.close ();} catch (exception ignored) {} this.fin = null; try {this.in.close ();} catch (exception ignored) {} ​​this.in = null;}} simpleWebserverManager =============== = =================================================== Java.text. *; import edu.oswego.cs.dl.util.concurrent. *; / ************ Responsible for establishing Serversocket and created, destroy SimpleWebserver ****** ******** / public class SimpleWebServerManager extends Thread {URL of the Encode (default UTF-8) private static String Encode = "UTF-8"; default log file name private static final String defaultLogFileName = "log.txt "; port private int port = 80;</p> <p>Parameter file private String iniFile = "webserver.ini"; log file name private String logFileName = null; private for reading the parameter file BufferedInputStream readini = null; storing parameters private static ConcurrentReaderHashMap ini = new ConcurrentReaderHashMap (); // All threads You can read it concurrent, but only synchronously written HashMap thread pool private pooledexecutor pool = null; the maximum number of threads in the thread pool private int maxPoolsize = 10; the minimum thread number in the thread pool private int minPoolsize = 1; request queue size Exceeding this request is rejected Private Static int RequestqueueSize = 50; the date format in the HTTP protocol Private Static Final SimpleDateFormat SDF = New SimpleDateFormat ("EEE, DD MMM YYYY HH: MM: SS ZZZ", Locale.us); Index Private static string [] indexfiles = null; timeout, refers to timeout (5 seconds) private static final int Timeout = 5 * 1000; private static int id = 0; private serverSocket SS = NULL ; private Socket socket = null; parameter file was last modified private long iniFileLastModified = 0L; the only examples of such references private static SimpleWebServerManager swmInstance = null; log private WebServerLogger log = null; private static final Object lock = new Object (); / ** * constructor * * @Exception i llegalArgumentException parameter error parameter file * @exception FileNotFoundException * @exception IOException not read the parameter file error * / public SimpleWebServerManager () throws IllegalArgumentException, FileNotFoundException, IOException {this.initProperties () Found; this.pool = new PooledExecutor (new BoundedBuffer (10 ), this.maxpoolsize; this.pool.setkeepalivetime (1000 * 60 * 5); thread survival time in the thread pool THISPOOL.SETMINIMPOOLSIZE (this.Poolsize); this.pool.createthreads (3); start () } / ** * Returns the only instance.</p> <p>The use of thread-safe Lazy Singleton design pattern * * @return SimpleWebServerManager instance * @exception IllegalArgumentException parameter error * @exception FileNotFoundException parameter file is not found * @exception IOException read the parameter file error * / public static SimpleWebServerManager getInstance () throws IllegalArgumentException, FileNotFoundException, IOEXCEPTION {if (SWMINSTANCE == NULL) {Synchronized (LOCK) {Double Protection, Guarantees only instantiate IF (SWMINSTANCE == NULL) SWMINSTANCE = New SimpleWebServerManager ();}} Return SWMINSTANCE;} / ** * Read parameters File, and check the parameters.</p> <p>* * First use Properties to load parameters, then deposited in-asynchronous read HashMap to improve the access efficiency of concurrent thread * * @Exception Illegal000Exception parameter syntax error * @Exception filenotfoundException parameter file No * @Exception ioException read parameter file error * / protected void initproperties () THROWS ILLEGALARGUMENTEXCEPTION, FILENOTFOANDEXCETION, IOEXCEPTION {Check if the properties file is used by other programs or manually modified, if yes, re-read this file file f = new file (this.inifile); if (F.Exists ()) {long newLastModified = f.lastModified (); if (newLastModified == 0) throw new IOException ( "profile:" this.iniFile "! read error"); else if (newLastModified> this.iniFileLastModified) file has changed {this.iniFileLastModified = newLastModified; Properties iniTmp = new Properties (); for loading parameters this.readini = new BufferedInputStream (new FileInputStream (this.iniFile)); iniTmp.load (this.readini); ConcurrentReaderHashMap c = New ConcurrentReaderHashMap (Initmp); Initmp = null; / ****************** Check Parameter Legacy ***************** ********* / / *********************************************************************** {port try { This.Port = integer.parseint ((string) C. Get ("port"));} Catch (Numberformatexception NFE) {throw new illegalargumentException ("Parameter error! The port number must be an integer (Property Error: / "Port /") ")");} log file name this.logfilename = ("logfile"); if (this.logfilename == null || this. logFileName.equals ( "")) this.logFileName = defaultLogFileName; number of threads in the thread pool up to try {this.maxPoolSize = Integer.parseInt ((String) c.get ( "MaxPoolSize"));} catch (NumberFormatException nfe) { Throw new illegalargumentException ("Parameter error! Thread pool maximum number of threads must be an integer (Property Error: /" MaxPoolSize / ")");} The minimum number of threads in the thread pool Try {this.minpoolsize =</p> <p>Integer.Parseint ("MINPOOLSIZE"));} Catch (NumberFormatexception NFE) {throw new illegalgumentException ("Parameter error! Thread pool minimum thread number must be an integer (Property Error: /" MINPoolsize / ") ");} / ******************* Add other global parameters ****************************** ** / / ** can add into INI to ** / boot WebserverLogger this.log = new webserverlogger (this.logfilename); ini.put ("logger", this.log); URL ENCODE INI.PUT (" Encode ", eNCode); Add server IP address to INI.PUT (" Serverip ", inetaddress.getlocalhost (). GetHostAddress ()); add the date format in the HTTP protocol to the parameter (SimpleDateFormat type) sdf.settimezone (Timezone.gettimezone ("GMT")); INI.PUT ("DateFormat", SDF); Adding a newline in INI.PUT ("Separator", System.GetProperty ("line.separator"); / ******************************************************* /} else { Delete the reboot from C. Remove ("port"); C.Remove ("logfile"); c.Remove ("MaxPoolsize"); C.Remove ("MINPOOLSIZE");} / *** ***** No need to reboot, changeable parameters ******* / root path string rp = (string) C.GET ("root"); if (rp! = Null&&! (New file " ) .exists ())) throw new illegalargumentException ("Parameter error! Root path does not exist (ProPE RTY Error: / "root /" not exist "); index files string indexs = (string) C.GET (" index "); if (indexs! = null&&! indexs.equals (")) {StringTokenizer token = New StringTokenizer (IndexS, ","); indexfiles = new string [token.countTokens ()]; for (int i = 0; i <indexfiles.length; i ) {indexfiles [i] = token.nextToken (); } Replace String in the parameter into string [] type C.PUT ("INDEX", IndexFiles);} else throw new illegalgumentException ("error!</p> <p>The index file name cannot be empty ("Listfiles"); if (! listfiles "); if (! listfiles"); if (! listfiles "); if (! listfiles.equalsignorecase) ") &&! listfiles.equalsignorecase (" no ")) throw new illegalgumentException (" Parameter error! Listfiles parameter cannot be empty (Property Error: / "ListFiles /" Must / "Yes /" OR / "NO /") " ); OUTPUT cache size try {string o = (string) c.get ("outputbuffer"); if (o == null || o.equals (")) o =" 128 "; integer.Parseint (O) Just check it out} Catch (NumberFormatexception NFE) {throw new illegalargumentException ("Parameter error! Send cache size must be an integer (Property error: /" outputbuffer / ")");} / ******* ************* Check the *********************** / INI.PUTALL (C); deposit parameter HashMap In the replacement of the original parameter c = null;}} else throw new filenotfoundexception ("Parameter file: this.inifile " is deleted! ");} / ** * GET port number * * @return port number * / Public int getPort;} / ** * get parameter hashmap * @return parameter HashMap * / protected map getproperties () {return ini;} / ** * get parameter file name * * @return parameter File name * / public string getpropertiesfilename () {RETUR n this.inifile;} public void run () {Try {this.ss = new serverSocket (this.port, requestqueueesize); non-receiving customer request while (! interrupted ()) {Try {this.socket = this.ss .accept (); this.socket.setsotimeout; this.initproperties (); pool.execute (new Simpleet, String.Valueof ( this.id), INI);} catch (socketexception e) {/ * Do not need to handle this Exception, the server will turn off the ServerSocket when it is abort, so accept () will throw this exception * /} catch (exception e) {other exception log.error (E.getMessage ());</p> <p>}}} Catch (Exception E) {/ * If it is InterruptedException, what does not do, because WebServer Shutdown This thread is used by Interrupted if (! (e instanceof interruptedException) {system.out.println ("/ NERROR:" E.getMessage () "please shutdown!"); system.out.println ();} * / log.error (E.GetMessage ()); system.err.println (); system.err.println "Error:" E.GetMessage () "please shutdown!"); System.err.println ();}} public void destroy ()}} all threads in the thread pool this.pool.shutdownAfterProcessingCurrentlyQueueue -tasks (); try {this.Socket.close ();} catch (exception ignored) {} ​​this.socket = null; try {this.ss.close ();} catch (exception ignored) {} ​​this.ss = null; try {this .readini.close ();} catch (Exception ignored) {} ​​this.close = null; this.log.cloSelog (); this.log = null;}} WebserverLogger: =========== =================================================== package hcc; import java.io. *; import java.text. *; import java.util. *; public class webserverlogger {temporary log information private stringbuffer messtmp = null; Time format in LOG PRIVATETIC FINAL DATEFORMAT logDateFormat = DateFormat.getDateTimeInstance (); for writing log stream (s instances common) private static PrintWriter log = null; // NOTE: PrintWriter has a synchronized / ** * WebServerLogger constructor * * @param logFileName log file The name (including path) * error @exception IOException open log file * / public WebServerLogger (String logFileName) throws IOException {log = new PrintWriter (new BufferedWriter (new FileWriter (logFileName, true)), true);</p> <p>} / ** * output log * * @param messageType type of information, such as error, warning * @param message content * / protected void doLog (String messageType, String message) {try {messTmp = new StringBuffer (); messTmp.append (MessageType this.logdateformat.format (new date ())); messtmp.append ("----"); messtmp.Append (Message); log.println (MesSTMP.TOString ()); log.flush ( );} catch (Exception ignored) {}} / ** * output log * * @param messageType type of information, such as error, warning * @param exception error * / protected void doLog (String messageType, Throwable exception) {try {messTmp = new stringbuffer (); messtmp.Append (MessageType this.logdateformat.format (new date ())); messtmp.append ("-"); messtmp.Append (Exception.toString ()); Messtmp. Append (System.GetProperty ("line.separator"); stacktracelement [] ste = exception.getStackTrace (); for (int i = 0, n = ste.length; i <n; i ) {messtmp.append (Stee [i] .tostring () system.getProperty ("line.separator"));} log.println (messtmp.tostring ()); log.flush ();} catch (exception ignored) {}} / ** * Error information * @Param Message Information * / Public Void Error (String Message) {this.dolog ("Error:", Message);} / ** * error message * * @Param throwable error * / public void error (throwable throwable ) {THIS.DOLOG ("Error:", throwable;} / ** * Warning information * * @Param Message information * / public void Warning (String Message) {this.dolog ("Warning:", Message; } / ** * Warning information * * @Param throwable error * / public void warning (thisdolog) {this.dolog ("Warning:", throwable;} / ** * normal information * * @Param Message information * / public void info (String Message) {this.dolog ("", message);</p> <p>} / ** * normal information * * @Param throwable error * / public void info (thion.dolog) {this.dolog ("", throwable);} / ** * normal information * * @Param Message information * / public Void Debug (String Message) {this.dolog ("debug:", message);} / ** * normal information * * @Param throwable error * / public void debug (thisdolog) {this.dolog ("debug:" Throwable);} / ** * Close the log stream (connection thread is not called) * / public void closelog () {Try {log.close ();} catch (exception ignored) {} ​​log not throw oException}} Webserver. INI =========================================================================================================== = ####################################################################################################################### Logfile = log.txt # Maximum and minimum threads in the thread pool (generally do not need to be changed) maxpoolsize = 10 minPoolsize = 3 ##################################################################################################################################################################################################################################################### ############# #ServerName: server name, such as: www.mywebsite.com servername = mywebsite # instead of "/" or "//" instead "/" root = E: / Share #index file name index = index.html, index.htm # Is Listing file listFiles = YES # Send cache size, unit: KB (generally do not change) OutputBuffer = 256 Supplemental description: ======== ==================================================== can customize the error page Simply add the following in the webserver.ini file: n Ot_Found = "File" File Name of the error page. Such as: not_found.html bad_request = "Error Request Parameter" error page file name. INTERNAL_ERROR = "Server Internal Error" error page file name.</p> <p>FORBIDEN = "No right access" file name of the error page. Other error types can be added yourself in your code. ============================================================================================================================================================================================================= ==============</p> <p>BTW: The public code that everyone can help in the industry, especially in China.</p> <p>I will open the source code of most of the programs I wrote.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-2607.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="2607" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.032</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'o7mwnJ71d5mJK_2FMLYsdGFNGbCs4H1po0PU5ToaLSJF8Z0QwusxEGz3NQGxQiSfVg1WuFDFwx0ZlC2P0nH4M_2FsA_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>