1. 程式人生 > >實現HTTP伺服器的三種方法

實現HTTP伺服器的三種方法

1、使用socket簡單實現http協議:

  1. import java.io.*;  
  2. import java.net.*;  
  3. /** 
  4.  * MyHttpServer 實現一個簡單的HTTP伺服器端,可以獲取使用者提交的內容 
  5.  * 並給使用者一個response 
  6.  * 因為時間的關係,對http頭的處理顯得不規範 
  7.  * 對於上傳附件,暫時只能解析只上傳一個附件而且附件位置在第一個的情況 
  8.  * 轉載請註明來自http://blog.csdn.net/sunxing007 
  9.  *  
  10.  * http://blog.csdn.net/sunxing007/article/details/4305956 
  11.  * **/
  12. publicclass
     MyHttpServer {  
  13.     //伺服器根目錄,post.html, upload.html都放在該位置
  14.     publicstatic String WEB_ROOT = "c:/root";  
  15.     //埠
  16.     privateint port;  
  17.     //使用者請求的檔案的url
  18.     private String requestPath;  
  19.     //mltipart/form-data方式提交post的分隔符, 
  20.     private String boundary = null;  
  21.     //post提交請求的正文的長度
  22.     privateint contentLength = 0;  
  23.     public MyHttpServer(String root, int port) {  
  24.         WEB_ROOT = root;  
  25.         this.port = port;  
  26.         requestPath = null;  
  27.     }  
  28.     //處理GET請求
  29.     privatevoid doGet(DataInputStream reader, OutputStream out) throws Exception {  
  30.         if (new File(WEB_ROOT + this.requestPath).exists()) {  
  31.             //從伺服器根目錄下找到使用者請求的檔案併發送回瀏覽器
  32.             InputStream fileIn = new FileInputStream(WEB_ROOT + this.requestPath);  
  33.             byte[] buf = newbyte[fileIn.available()];  
  34.             fileIn.read(buf);  
  35.             out.write(buf);  
  36.             out.close();  
  37.             fileIn.close();  
  38.             reader.close();  
  39.             System.out.println("request complete.");  
  40.         }  
  41.     }  
  42.     //處理post請求
  43.     privatevoid doPost(DataInputStream reader, OutputStream out) throws Exception {  
  44.         String line = reader.readLine();  
  45.         while (line != null) {  
  46.             System.out.println(line);  
  47.             line = reader.readLine();  
  48.             if ("".equals(line)) {  
  49.                 break;  
  50.             } elseif (line.indexOf("Content-Length") != -1) {  
  51.                 this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));  
  52.             }  
  53.             //表明要上傳附件, 跳轉到doMultiPart方法。
  54.             elseif(line.indexOf("multipart/form-data")!= -1){  
  55.                 //得multiltipart的分隔符
  56.                 this.boundary = line.substring(line.indexOf("boundary") + 9);  
  57.                 this.doMultiPart(reader, out);  
  58.                 return;  
  59.             }  
  60.         }  
  61.         //繼續讀取普通post(沒有附件)提交的資料
  62.         System.out.println("begin reading posted data......");  
  63.         String dataLine = null;  
  64.         //使用者傳送的post資料正文
  65.         byte[] buf = {};  
  66.         int size = 0;  
  67.         if (this.contentLength != 0) {  
  68.             buf = newbyte[this.contentLength];  
  69.             while(size<this.contentLength){  
  70.                 int c = reader.read();  
  71.                 buf[size++] = (byte)c;  
  72.             }  
  73.             System.out.println("The data user posted: " + new String(buf, 0, size));  
  74.         }  
  75.         //傳送回瀏覽器的內容
  76.         String response = "";  
  77.         response += "HTTP/1.1 200 OK/n";  
  78.         response += "Server: Sunpache 1.0/n";  
  79.         response += "Content-Type: text/html/n";  
  80.         response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT/n";  
  81.         response += "Accept-ranges: bytes";  
  82.         response += "/n";  
  83.         String body = "<html><head><title>test server</title></head><body><p>post ok:</p>" + new String(buf, 0, size) + "</body></html>";  
  84.         System.out.println(body);  
  85.         out.write(response.getBytes());  
  86.         out.write(body.getBytes());  
  87.         out.flush();  
  88.         reader.close();  
  89.         out.close();  
  90.         System.out.println("request complete.");  
  91.     }  
  92.     //處理附件
  93.     privatevoid doMultiPart(DataInputStream reader, OutputStream out) throws Exception {  
  94.         System.out.println("doMultiPart ......");  
  95.         String line = reader.readLine();  
  96.         while (line != null) {  
  97.             System.out.println(line);  
  98.             line = reader.readLine();  
  99.             if ("".equals(line)) {  
  100.                 break;  
  101.             } elseif (line.indexOf("Content-Length") != -1) {  
  102.                 this.contentLength = Integer.parseInt(line.substring(line.indexOf("Content-Length") + 16));  
  103.                 System.out.println("contentLength: " + this.contentLength);  
  104.             } elseif (line.indexOf("boundary") != -1) {  
  105.                 //獲取multipart分隔符
  106.                 this.boundary = line.substring(line.indexOf("boundary") + 9);  
  107.             }  
  108.         }  
  109.         System.out.println("begin get data......");  
  110.         /*下面的註釋是一個瀏覽器傳送帶附件的請求的全文,所有中文都是說明性的文字***** 
  111.         <HTTP頭部內容略> 
  112.         ............ 
  113.         Cache-Control: no-cache 
  114.         <這裡有一個空行,表明接下來的內容都是要提交的正文> 
  115.         -----------------------------7d925134501f6<這是multipart分隔符> 
  116.         Content-Disposition: form-data; name="myfile"; filename="mywork.doc" 
  117.         Content-Type: text/plain 
  118.         <附件正文>........................................ 
  119.         ................................................. 
  120.         -----------------------------7d925134501f6<這是multipart分隔符> 
  121.         Content-Disposition: form-data; name="myname"<其他欄位或附件> 
  122.         <這裡有一個空行> 
  123.         <其他欄位或附件的內容> 
  124.         -----------------------------7d925134501f6--<這是multipart分隔符,最後一個分隔符多兩個-> 
  125.         ****************************************************************/
  126.         /** 
  127.          * 上面的註釋是一個帶附件的multipart型別的POST的全文模型, 
  128.          * 要把附件去出來,就是要找到附件正文的起始位置和結束位置 
  129.          * **/
  130.         if (this.contentLength != 0) {  
  131.             //把所有的提交的正文,包括附件和其他欄位都先讀到buf.
  132.             byte[] buf = newbyte[this.contentLength];  
  133.             int totalRead = 0;  
  134.             int size = 0;  
  135.             while (totalRead < this.contentLength) {  
  136.                 size = reader.read(buf, totalRead, this.contentLength - totalRead);  
  137.                 totalRead += size;  
  138.             }  
  139.             //用buf構造一個字串,可以用字串方便的計算出附件所在的位置
  140.             String dataString = new String(buf, 0, totalRead);  
  141.             System.out.println("the data user posted:/n" + dataString);  
  142.             int pos = dataString.indexOf(boundary);  
  143.             //以下略過4行就是第一個附件的位置
  144.             pos = dataString.indexOf("/n", pos) + 1;  
  145.             pos = dataString.indexOf("/n", pos) + 1;  
  146.             pos = dataString.indexOf("/n", pos) + 1;  
  147.             pos = dataString.indexOf("/n", pos) + 1;  
  148.             //附件開始位置
  149.             int start = dataString.substring(0, pos).getBytes().length;  
  150.             pos = dataString.indexOf(boundary+"--", pos) - 4;  
  151.             //附件結束位置
  152.             int end = dataString.substring(0, pos).getBytes().length;  
  153.             //以下找出filename
  154.             int fileNameBegin = dataString.indexOf("filename") + 10;  
  155.             int fileNameEnd = dataString.indexOf("/n", fileNameBegin);  
  156.             String fileName = dataString.substring(fileNameBegin, fileNameEnd);  
  157.             /** 
  158.              * 有時候上傳的檔案顯示完整的檔名路徑,比如c:/my file/somedir/project.doc 
  159.              * 但有時候只顯示檔案的名字,比如myphoto.jpg. 
  160.              * 所以需要做一個判斷。 
  161.             */
  162.             if(fileName.lastIndexOf("//")!=-1){  
  163.                 fileName = fileName.substring(fileName.lastIndexOf("//") + 1);  
  164.             }  
  165.             fileName = fileName.substring(0, fileName.length()-2);  
  166.             OutputStream fileOut = new FileOutputStream("c://" + fileName);  
  167.             fileOut.write(buf, start, end-start);  
  168.             fileOut.close();  
  169.             fileOut.close();  
  170.         }  
  171.         String response = "";  
  172.         response += "HTTP/1.1 200 OK/n";  
  173.         response += "Server: Sunpache 1.0/n";  
  174.         response += "Content-Type: text/html/n";  
  175.         response += "Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT/n";  
  176.         response += "Accept-ranges: bytes";  
  177.         response += "/n";  
  178.         out.write("<html><head><title>test server</title></head><body><p>Post is ok</p></body></html>".getBytes());  
  179.         out.flush();  
  180.         reader.close();  
  181.         System.out.println("request complete.");  
  182.     }  
  183.     publicvoid service() throws Exception {  
  184.         ServerSocket serverSocket = new ServerSocket(this.port);  
  185.         System.out.println("server is ok.");  
  186.         //開啟serverSocket等待使用者請求到來,然後根據請求的類別作處理
  187.         //在這裡我只針對GET和POST作了處理
  188.         //其中POST具有解析單個附件的能力
  189.         while (true) {  
  190.             try {  
  191.                 Socket socket = serverSocket.accept();  
  192.                 System.out.println("new request coming.");  
  193.                 DataInputStream reader = new DataInputStream((socket.getInputStream()));  
  194.                 String line = reader.readLine();  
  195.                 if(line!=null){  
  196.                      String method = line.substring(04).trim();  
  197.                      OutputStream out = socket.getOutputStream();  
  198.                      this.requestPath = line.split(" ")[1];  
  199.                      System.out.println(method);  
  200.                      if ("GET".equalsIgnoreCase(method)) {  
  201.                          System.out.println("do get......");  
  202.                          this.doGet(reader, out);  
  203.                      } elseif ("POST".equalsIgnoreCase(method)) {  
  204.                          System.out.println("do post......");  
  205.                          this.doPost(reader, out);  
  206.                      }  
  207.                 }else{  
  208.                     System.err.println("line is null!");  
  209.                 }  
  210.                 socket.close();  
  211.                 System.out.println("socket closed.");  
  212.             } catch (Exception e) {  
  213.                 e.printStackTrace();  
  214.             }  
  215.         }  
  216.     }  
  217.     publicstaticvoid main(String args[]) throws Exception {  
  218.         MyHttpServer server = new MyHttpServer("c:/root"8080);  
  219.         server.service();  
  220.     }  
  221. }  

2、使用jdk自導的httpserver元件

  1. import java.io.IOException;  
  2. import java.io.OutputStream;  
  3. import java.net.InetSocketAddress;  
  4. import java.util.Iterator;  
  5. import java.util.List;  
  6. import java.util.Set;  
  7. import java.util.concurrent.Executors;  
  8. import com.sun.net.httpserver.Headers;  
  9. import com.sun.net.httpserver.HttpExchange;  
  10. import com.sun.net.httpserver.HttpHandler;  
  11. import com.sun.net.httpserver.HttpServer;  
  12. //在eclipse中會出現Access restriction: The type Headers is not accessible due to restriction on required library
  13. //解決辦法:把Windows-Preferences-Java-Complicer- Errors/Warnings裡面的Deprecated and restricted API中的Forbidden references(access rules)選為Warning就可以編譯通過。
  14. /** 
  15.  * 使用jdk自帶sun httpserver元件構建Http伺服器, 
  16.  * JDK自帶的HttpServer是一個非常輕量級的Http服務端框架,但是它非常靈活,易於擴充套件, 
  17.  * @author Administrator 
  18.  * 
  19.  */
  20. publicclass HttpServerDemo {  
  21.     publicstaticvoid main(String[] args) throws IOException {  
  22.         InetSocketAddress addr = new InetSocketAddress(8080);  
  23.         HttpServer server = HttpServer.create(addr, 0);  
  24.         server.createContext("/"new MyHandler());  
  25.         server.setExecutor(Executors.newCachedThreadPool());  
  26.         server.start();  
  27.         System.out.println("Server is listening on port 8080");  
  28.     }  
  29. }  
  30. class MyHandler implements HttpHandler {  
  31.     publicvoid handle(HttpExchange exchange) throws IOException {  
  32.         String requestMethod = exchange.getRequestMethod();  
  33.         System.out.println("處理新請求:"+requestMethod);  
  34.         if (requestMethod.equalsIgnoreCase("GET")) {  
  35.             Headers responseHeaders = exchange.getResponseHeaders();  
  36.             responseHeaders.set("Content-Type""text/plain");  
  37.             exchange.sendResponseHeaders(2000);  
  38.             OutputStream responseBody = exchange.getResponseBody();  
  39.             Headers requestHeaders = exchange.getRequestHeaders();  
  40.             Set<String> keySet = requestHeaders.keySet();  
  41.             Iterator<String> iter = keySet.iterator();  
  42.             while (iter.hasNext()) {  
  43.                 String key = iter.next();  
  44.                 List values = requestHeaders.get(key);  
  45.                 String s = key + " = " + values.toString() + "\n";  
  46.                 responseBody.write(s.getBytes());  
  47.             }  
  48.             responseBody.close();  
  49.         }  
  50.     }  
  51. }  

3、使用apache開源的httpcore元件實現。

  1. /* 
  2.  * ==================================================================== 
  3.  * Licensed to the Apache Software Foundation (ASF) under one 
  4.  * or more contributor license agreements.  See the NOTICE file 
  5.  * distributed with this work for additional information 
  6.  * regarding copyright ownership.  The ASF licenses this file 
  7.  * to you under the Apache License, Version 2.0 (the 
  8.  * "License"); you may not use this file except in compliance 
  9.  * with the License.  You may obtain a copy of the License at 
  10.  * 
  11.  *   http://www.apache.org/licenses/LICENSE-2.0 
  12.  * 
  13.  * Unless required by applicable law or agreed to in writing, 
  14.  * software distributed under the License is distributed on an 
  15.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
  16.  * KIND, either express or implied.  See the License for the 
  17.  * specific language governing permissions and limitations 
  18.  * under the License. 
  19.  * ==================================================================== 
  20.  * 
  21.  * This software consists of voluntary contributions made by many 
  22.  * individuals on behalf of the Apache Software Foundation.  For more 
  23.  * information on the Apache Software Foundation, please see 
  24.  * <http://www.apache.org/>. 
  25.  * 
  26.  */
  27. package org.apache.http.examples;  
  28. import java.io.File;  
  29. import java.io.IOException;  
  30. import java.io.InterruptedIOException;  
  31. import java.net.ServerSocket;  
  32. import java.net.Socket;  
  33. import java.net.URL;  
  34. import java.net.URLDecoder;  
  35. import java.nio.charset.Charset;  
  36. import java.security.KeyStore;  
  37. import java.util.Locale;  
  38. import org.apache.http.ConnectionClosedException;  
  39. import org.apache.http.HttpConnectionFactory;  
  40. import org.apache.http.HttpEntity;  
  41. import org.apache.http.HttpEntityEnclosingRequest;  
  42. import org.apache.http.HttpException;  
  43. import org.apache.http.HttpRequest;  
  44. import org.apache.http.HttpResponse;  
  45. import org.apache.http.HttpServerConnection;  
  46. import org.apache.http.HttpStatus;  
  47. import org.apache.http.MethodNotSupportedException;  
  48. import org.apache.http.entity.ContentType;  
  49. import org.apache.http.entity.FileEntity;  
  50. import org.apache.http.entity.StringEntity;  
  51. import org.apache.http.impl.DefaultBHttpServerConnection;  
  52. import org.apache.http.impl.DefaultBHttpServerConnectionFactory;  
  53. import org.apache.http.protocol.BasicHttpContext;  
  54. import org.apache.http.protocol.HttpContext;  
  55. import org.apache.http.protocol.HttpProcessor;  
  56. import org.apache.http.protocol.HttpProcessorBuilder;  
  57. import org.apache.http.protocol.HttpRequestHandler;  
  58. import org.apache.http.protocol.HttpService;  
  59. import org.apache.http.protocol.ResponseConnControl;  
  60. import org.apache.http.protocol.ResponseContent;  
  61. import org.apache.http.protocol.ResponseDate;  
  62. import org.apache.http.protocol.ResponseServer;  
  63. import org.apache.http.protocol.UriHttpRequestHandlerMapper;  
  64. import org.apache.http.util.EntityUtils;  
  65. import javax.net.ssl.KeyManager;  
  66. import javax.net.ssl.KeyManagerFactory;  
  67. import javax.net.ssl.SSLContext;  
  68. import javax.net.ssl.SSLServerSocketFactory;  
  69. /** 
  70.  * Basic, yet fully functional and spec compliant, HTTP/1.1 file server. 
  71.  */
  72. publicclass ElementalHttpServer {  
  73.     publicstaticvoid main(String[] args) throws Exception {  
  74.         /** 
  75.         if (args.length < 1) { 
  76.             System.err.println("Please specify document root directory"); 
  77.             System.exit(1); 
  78.         } 
  79.         // Document root directory 
  80.         String docRoot = args[0];*/
  81.          String docRoot="c:/root";  
  82.         int port = 8080;  
  83.         if (args.length >= 2) {  
  84.             port = Integer.parseInt(args[1]);  
  85.         }  
  86.         // Set up the HTTP protocol processor
  87.         HttpProcessor httpproc = HttpProcessorBuilder.create()  
  88.                 .add(new ResponseDate())  
  89.                 .add(new ResponseServer("Test/1.1"))  
  90.                 .add(new ResponseContent())  
  91.                 .add(new ResponseConnControl()).build();  
  92.         // Set up request handlers
  93.         UriHttpRequestHandlerMapper reqistry = new UriHttpRequestHandlerMapper();  
  94.         reqistry.register("*"new HttpFileHandler(docRoot));  
  95.         // Set up the HTTP service
  96.         HttpService httpService = new HttpService(httpproc, reqistry);  
  97.         SSLServerSocketFactory sf = null;  
  98.         if (port == 8443) {  
  99.             // Initialize SSL context
  100.             ClassLoader cl = ElementalHttpServer.class.getClassLoader();  
  101.             URL url = cl.getResource("my.keystore");  
  102.             if (url == null) {  
  103.                 System.out.println("Keystore not found");  
  104.                 System.exit(1);  
  105.             }  
  106.             KeyStore keystore  = KeyStore.getInstance("jks");  
  107.             keystore.load(url.openStream(), "secret".toCharArray());  
  108.             KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(  
  109.                     KeyManagerFactory.getDefaultAlgorithm());  
  110.             kmfactory.init(keystore, "secret".toCharArray());  
  111.             KeyManager[] keymanagers = kmfactory.getKeyManagers();  
  112.             SSLContext sslcontext = SSLContext.getInstance("TLS");  
  113.             sslcontext.init(keymanagers, nullnull);  
  114.             sf = sslcontext.getServerSocketFactory();  
  115.         }  
  116.         Thread t = new RequestListenerThread(port, httpService, sf);  
  117.         t.setDaemon(false);  
  118.         t.start();  
  119.     }  
  120.     staticclass HttpFileHandler implements HttpRequestHandler  {  
  121.         privatefinal String docRoot;  
  122.         public HttpFileHandler(final String docRoot) {  
  123.             super();  
  124.             this.docRoot = docRoot;  
  125.         }  
  126.         publicvoid handle(  
  127.                 final HttpRequest request,  
  128.                 final HttpResponse response,  
  129.                 final HttpContext context) throws HttpException, IOException {  
  130.             String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);  
  131.             if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {  
  132.                 thrownew MethodNotSupportedException(method + " method not supported");  
  133.             }  
  134.             String target = request.getRequestLine().getUri();  
  135.             if (request instanceof HttpEntityEnclosingRequest) {  
  136.                 HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();  
  137.                 byte[] entityContent = EntityUtils.toByteArray(entity);  
  138.                 System.out.println("Incoming entity content (bytes): " + entityContent.length);  
  139.             }  
  140.             final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8"));  
  141.             if (!file.exists()) {  
  142.                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);  
  143.                 StringEntity entity = new StringEntity(  
  144.                         "<html><body><h1>File" + file.getPath() +  
  145.                         " not found</h1></body></html>",  
  146.                         ContentType.create("text/html""UTF-8"));  
  147.                 response.setEntity(entity);  
  148.                 System.out.println("File " + file.getPath() + " not found");  
  149.             } elseif (!file.canRead() || file.isDirectory()) {  
  150.                 response.setStatusCode(HttpStatus.SC_FORBIDDEN);  
  151.                 StringEntity entity = new StringEntity(  
  152.                         "<html><body><h1>Access denied</h1></body></html>",  
  153.                         ContentType.create("text/html""UTF-8"));  
  154.                 response.setEntity(entity);  
  155.                 System.out.println("Cannot read file " + file.getPath());  
  156.             } else {  
  157.                 response.setStatusCode(HttpStatus.SC_OK);  
  158.                 FileEntity body = new FileEntity(file, ContentType.create("text/html", (Charset) null));  
  159.                 response.setEntity(body);  
  160.                 System.out.println("Serving file " + file.getPath());  
  161.             }  
  162.         }  
  163.     }  
  164.     staticclass RequestListenerThread extends Thread {  
  165.         privatefinal HttpConnectionFactory<DefaultBHttpServerConnection> connFactory;  
  166.         privatefinal ServerSocket serversocket;  
  167.         privatefinal HttpService httpService;  
  168.         public RequestListenerThread(  
  169.                 finalint port,  
  170.                 final HttpService httpService,  
  171.                 final SSLServerSocketFactory sf) throws IOException {  
  172.             this.connFactory = DefaultBHttpServerConnectionFactory.INSTANCE;  
  173.             this.serversocket = sf != null ? sf.createServerSocket(port) : new ServerSocket(port);  
  174.             this.httpService = httpService;  
  175.         }  
  176.         @Override
  177.         publicvoid run() {  
  178.             System.out.println("Listening on port " + this.serversocket.getLocalPort());  
  179.             while (!Thread.interrupted()) {  
  180.                 try {  
  181.                     // Set up HTTP connection
  182.                     Socket socket = this.serversocket.accept();  
  183.                     System.out.println("Incoming connection from " + socket.getInetAddress());  
  184.                     HttpServerConnection conn = this.connFactory.createConnection(socket);  
  185.                     // Start worker thread
  186.                     Thread t = new WorkerThread(this.httpService, conn);  
  187.                     t.setDaemon(true);  
  188.                     t.start();  
  189.                 } catch (InterruptedIOException ex) {  
  190.                     break;  
  191.                 } catch (IOException e) {  
  192.                     System.err.println("I/O error initialising connection thread: "
  193.                             + e.getMessage());  
  194.                     break;  
  195.                 }  
  196.             }  
  197.         }  
  198.     }  
  199.     staticclass WorkerThread extends Thread {  
  200.         privatefinal HttpService httpservice;  
  201.         privatefinal HttpServerConnection conn;  
  202.         public WorkerThread(  
  203.                 final HttpService httpservice,  
  204.                 final HttpServerConnection conn) {  
  205.             super();  
  206.             this.httpservice = httpservice;  
  207.             this.conn = conn;  
  208.         }  
  209.         @Override
  210.         publicvoid run() {  
  211.             System.out.println("New connection thread");  
  212.             HttpContext context = new BasicHttpContext(null);  
  213.             try {  
  214.                 while (!Thread.interrupted() && this.conn.isOpen()) {  
  215.                     this.httpservice.handleRequest(this.conn, context);  
  216.                 }  
  217.             } catch (ConnectionClosedException ex) {  
  218.                 System.err.println("Client closed connection");  
  219.             } catch (IOException ex) {  
  220.                 System.err.println("I/O error: " + ex.getMessage());  
  221.             } catch (HttpException ex) {  
  222.                 System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());  
  223.             } finally {  
  224.                 try {  
  225.                     this.conn.shutdown();  
  226.                 } catch