java实现轻量型http代理服务器示例

 更新时间:2014年04月11日 09:30:26   作者:  
这篇文章主要介绍了java实现轻量型http代理服务器示例,需要的朋友可以参考下

复制代码 代码如下:

package cn.liangjintang.httpproxy;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class HttpProxy {
 static long threadCount = 0;
 int myTcpPort = 8080;
 private ServerSocket myServerSocket;
 private Thread myThread;

 public HttpProxy(int port) throws IOException {
  myTcpPort = port;
  myServerSocket = new ServerSocket(myTcpPort);
  myThread = new Thread(new Runnable() {
   public void run() {
    try {
     while (true)
      new HTTPSession(myServerSocket.accept());
    } catch (IOException ioe) {
    }
   }
  });
  myThread.setDaemon(true);
  myThread.start();
 }

 /**
  * Stops the server.
  */

 public void stop() {
  try {
   myServerSocket.close();
   myThread.join();
  } catch (IOException ioe) {
  } catch (InterruptedException e) {
  }
 }

 public class HTTPSession implements Runnable {
  private Socket mySocket;

  public HTTPSession(Socket s) {
   mySocket = s;
   Thread t = new Thread(this);
   t.setDaemon(true);
   t.start();
  }

  @Override
  public void run() {
   try {
    ++threadCount;

    InputStream is = mySocket.getInputStream();
    if (is == null)
     return;
    final int bufsize = 8192;
    byte[] buf = new byte[bufsize];
    int splitbyte = 0;
    int rlen = 0;
    {
     int read = is.read(buf, 0, bufsize);
     while (read > 0) {
      rlen += read;
      splitbyte = findHeaderEnd(buf, rlen);
      if (splitbyte > 0)
       break;
      read = is.read(buf, rlen, bufsize - rlen);
     }
     ByteArrayInputStream hbis = new ByteArrayInputStream(buf,
       0, rlen);
     BufferedReader hin = new BufferedReader(
       new InputStreamReader(hbis));
     Host host = new Host();
     {
      String string;
      boolean flag = false;
      while ((string = hin.readLine()) != null) {
       if (string.toLowerCase().startsWith("host:")) {
        host.host = string;
        flag = true;
       }
       System.out.println(string);
      }
      if (!flag) {
       mySocket.getOutputStream().write(
         "error!".getBytes());
       mySocket.close();
       return;
      }
     }

     host.cal();
     System.out.println("address:[" + host.address + "]port:"
       + host.port + "\n-------------------\n");

     try {
      pipe(buf, rlen, mySocket, mySocket.getInputStream(),
        mySocket.getOutputStream(), host);
     } catch (Exception e) {
      System.out.println("Run Exception!");
      e.printStackTrace();
     }
    }

   } catch (Exception e) {
   }
   System.out.println("threadcount:" + --threadCount);
  }

  /**
   * finad http header
   **/
  private int findHeaderEnd(final byte[] buf, int rlen) {
   int splitbyte = 0;
   while (splitbyte + 3 < rlen) {
    if (buf[splitbyte] == '\r' && buf[splitbyte + 1] == '\n'
      && buf[splitbyte + 2] == '\r'
      && buf[splitbyte + 3] == '\n')
     return splitbyte + 4;
    splitbyte++;
   }
   return 0;
  }

  void pipe(byte[] request, int requestLen, Socket client,
    InputStream clientIS, OutputStream clientOS, Host host)
    throws Exception {
   byte bytes[] = new byte[1024 * 32];
   Socket socket = new Socket(host.address, host.port);
   socket.setSoTimeout(3000);
   OutputStream os = socket.getOutputStream();
   InputStream is = socket.getInputStream();
   try {
    do {
     os.write(request, 0, requestLen);
     int resultLen = 0;
     try {
      while ((resultLen = is.read(bytes)) != -1
        && !mySocket.isClosed() && !socket.isClosed()) {
       clientOS.write(bytes, 0, resultLen);
      }
     } catch (Exception e) {
      System.out.println("target Socket exception:"
        + e.toString());
     }

     System.out.println("proxy requset-connect broken,socket:"
       + socket.hashCode());
    } while (!mySocket.isClosed()
      && (requestLen = clientIS.read(request)) != -1);
   } catch (Exception e) {
    System.out.println("client Socket exception:" + e.toString());
   }

   System.out.println("end,socket:" + socket.hashCode());
   os.close();
   is.close();
   clientIS.close();
   clientOS.close();
   socket.close();
   mySocket.close();

  }

  // target Host info
  final class Host {
   public String address;
   public int port;
   public String host;

   public boolean cal() {
    if (host == null)
     return false;
    int start = host.indexOf(": ");
    if (start == -1)
     return false;
    int next = host.indexOf(':', start + 2);
    if (next == -1) {
     port = 80;
     address = host.substring(start + 2);
    } else {
     address = host.substring(start + 2, next);
     port = Integer.valueOf(host.substring(next + 1));
    }
    return true;
   }
  }
 }

 public static void main(String[] args) {
  try {
   new HttpProxy(8580);
  } catch (IOException ioe) {
   System.err.println("Couldn't start server:\n" + ioe);
   System.exit(-1);
  }
  System.out.println("start!");
  try {
   System.in.read();
  } catch (Throwable t) {
  }
  System.out.println("stop!");
 }
}

相关文章

  • Java内存泄漏问题排查与解决

    Java内存泄漏问题排查与解决

    大家好,本篇文章主要讲的是Java内存泄漏问题排查与解决,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • java swing编程入门代码编写(java编程入门)

    java swing编程入门代码编写(java编程入门)

    Swing是一个为Java设计的GUI工具包,是用来做UI界面的,大家看了下面的介绍就要吧自己做java界面了
    2013-12-12
  • springboot +rabbitmq+redis实现秒杀示例

    springboot +rabbitmq+redis实现秒杀示例

    本文主要介绍了springboot +rabbitmq+redis实现秒杀示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 浅析Java中SimpleDateFormat为什么是线程不安全的

    浅析Java中SimpleDateFormat为什么是线程不安全的

    SimpleDateFormat是Java中用于日期时间格式化的一个类,它提供了对日期的解析和格式化能力,本文主要来和大家一起探讨一下SimpleDateFormat为什么是线程不安全的,感兴趣的可以了解下
    2024-02-02
  • Mybatis-Plus接口BaseMapper与Services使用详解

    Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 解读System.getProperty("ENM_HOME")中的值从哪获取的

    解读System.getProperty("ENM_HOME")中的值从哪获取的

    这篇文章主要介绍了解读System.getProperty("ENM_HOME")中的值从哪获取的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Spring Boot 项目搭建教程及注解

    Spring Boot 项目搭建教程及注解

    下面小编就为大家带来一篇Spring Boot 项目搭建教程及注解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 一文带你了解gson如何序列化子类

    一文带你了解gson如何序列化子类

    这篇文章主要为大家详细介绍了gson如何序列化子类的相关知识,文中的示例代码讲解详细,具有一定的学习和借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • 详解java实现遍历二叉树的三种情况

    详解java实现遍历二叉树的三种情况

    这篇文章主要介绍了java实现遍历二叉树的三种情况,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • java中MultipartFile和File最简单的互相转换示例

    java中MultipartFile和File最简单的互相转换示例

    这篇文章主要给大家介绍了关于java中MultipartFile和File最简单的互相转换的相关资料,MultipartFile和File都是Java中用于处理文件上传的类,MultipartFile用于处理上传的文件,File用于处理本地磁盘上的文件,需要的朋友可以参考下
    2023-09-09

最新评论