HttpServer.java
上传用户:songled
上传日期:2022-07-14
资源大小:94k
文件大小:5k
源码类别:

进程与线程

开发平台:

Java

  1. import java.io.*;
  2. import java.net.*;
  3. // uses ObjectFIFO from chapter 18
  4. public class HttpServer extends Object {
  5. // currently available HttpWorker objects
  6. private ObjectFIFO idleWorkers;
  7. // all HttpWorker objects
  8. private HttpWorker[] workerList;
  9. private ServerSocket ss;
  10. private Thread internalThread;
  11. private volatile boolean noStopRequested;
  12. public HttpServer(
  13. File docRoot,
  14. int port,
  15. int numberOfWorkers,
  16. int maxPriority
  17. ) throws IOException {
  18. // Allow a max of 10 sockets to queue up 
  19. // waiting for accpet().
  20. ss = new ServerSocket(port, 10); 
  21. if ( ( docRoot == null ) || 
  22.  !docRoot.exists() || 
  23.  !docRoot.isDirectory() 
  24.    ) {
  25. throw new IOException("specified docRoot is null " +
  26. "or does not exist or is not a directory");
  27. }
  28. // ensure that at least one worker is created
  29. numberOfWorkers = Math.max(1, numberOfWorkers);
  30. // Ensure: 
  31. // (minAllowed + 2) <= serverPriority <= (maxAllowed - 1)
  32. // which is generally:
  33. //   3 <= serverPriority <= 9
  34. int serverPriority = Math.max(
  35. Thread.MIN_PRIORITY + 2, 
  36. Math.min(maxPriority, Thread.MAX_PRIORITY - 1)
  37. );
  38. // Have the workers run at a slightly lower priority so 
  39. // that new requests are handled with more urgency than 
  40. // in-progress requests.
  41. int workerPriority = serverPriority - 1;
  42. idleWorkers = new ObjectFIFO(numberOfWorkers);
  43. workerList = new HttpWorker[numberOfWorkers];
  44. for ( int i = 0; i < numberOfWorkers; i++ ) {
  45. // Workers get a reference to the FIFO to add 
  46. // themselves back in when they are ready to 
  47. // handle a new request.
  48. workerList[i] = new HttpWorker(
  49. docRoot, workerPriority, idleWorkers);
  50. }
  51. // Just before returning, the thread should be 
  52. // created and started.
  53. noStopRequested = true;
  54. Runnable r = new Runnable() {
  55. public void run() {
  56. try {
  57. runWork();
  58. } catch ( Exception x ) {
  59. // in case ANY exception slips through
  60. x.printStackTrace(); 
  61. }
  62. }
  63. };
  64. internalThread = new Thread(r);
  65. internalThread.setPriority(serverPriority); 
  66. internalThread.start();
  67. }
  68. private void runWork() {
  69. System.out.println(
  70. "HttpServer ready to receive requests");
  71. while ( noStopRequested ) {
  72. try {
  73. Socket s = ss.accept();
  74. if ( idleWorkers.isEmpty() ) {
  75. System.out.println(
  76. "HttpServer too busy, denying request");
  77. BufferedWriter writer = 
  78. new BufferedWriter(
  79. new OutputStreamWriter(
  80. s.getOutputStream()));
  81. writer.write("HTTP/1.0 503 Service " +
  82. "Unavailablernrn");
  83. writer.flush();
  84. writer.close();
  85. writer = null;
  86. } else {
  87. // No need to be worried that idleWorkers 
  88. // will suddenly be empty since this is the 
  89. // only thread removing items from the queue.
  90. HttpWorker worker = 
  91. (HttpWorker) idleWorkers.remove();
  92. worker.processRequest(s);
  93. }
  94. } catch ( IOException iox ) {
  95. if ( noStopRequested ) {
  96. iox.printStackTrace();
  97. }
  98. } catch ( InterruptedException x ) {
  99. // re-assert interrupt
  100. Thread.currentThread().interrupt(); 
  101. }
  102. }
  103. }
  104. public void stopRequest() {
  105. noStopRequested = false;
  106. internalThread.interrupt();
  107. for ( int i = 0; i < workerList.length; i++ ) {
  108. workerList[i].stopRequest();
  109. }
  110. if ( ss != null ) {
  111. try { ss.close(); } catch ( IOException iox ) { }
  112. ss = null;
  113. }
  114. }
  115. public boolean isAlive() {
  116. return internalThread.isAlive();
  117. }
  118. private static void usageAndExit(String msg, int exitCode) {
  119. System.err.println(msg);
  120. System.err.println("Usage: java HttpServer <port> " +
  121. "<numWorkers> <documentRoot>");
  122. System.err.println("   <port> - port to listen on " +
  123. "for HTTP requests");
  124. System.err.println("   <numWorkers> - number of " +
  125. "worker threads to create");
  126. System.err.println("   <documentRoot> - base " +
  127. "directory for HTML files");
  128. System.exit(exitCode);
  129. }
  130. public static void main(String[] args) {
  131. if ( args.length != 3 ) {
  132. usageAndExit("wrong number of arguments", 1);
  133. }
  134. String portStr = args[0];
  135. String numWorkersStr = args[1];
  136. String docRootStr = args[2];
  137. int port = 0;
  138. try {
  139. port = Integer.parseInt(portStr);
  140. } catch ( NumberFormatException x ) {
  141. usageAndExit("could not parse port number from '" + 
  142. portStr + "'", 2);
  143. }
  144. if ( port < 1 ) {
  145. usageAndExit("invalid port number specified: " + 
  146. port, 3);
  147. }
  148. int numWorkers = 0;
  149. try {
  150. numWorkers = Integer.parseInt(numWorkersStr);
  151. } catch ( NumberFormatException x ) {
  152. usageAndExit(
  153. "could not parse number of workers from '" + 
  154. numWorkersStr + "'", 4);
  155. }
  156. File docRoot = new File(docRootStr);
  157. try {
  158. new HttpServer(docRoot, port, numWorkers, 6);
  159. } catch ( IOException x ) {
  160. x.printStackTrace();
  161. usageAndExit("could not construct HttpServer", 5);
  162. }
  163. }
  164. }