java实现轻量型http代理服务器示例
发布时间:2021-10-05 18:14:20
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!");
}
}
猜你喜欢
- * 是许多框架底层实现的基础,比如Spirng的AOP等,其实弄清楚了 * 的实现原理,它就没那么神奇了,下面就来通过案例和分析JDK
- 本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码,具体内容如下①
- 0.前言文章需求:对于学生来说,目前网上确实没有比较统一而且质量好的支付教程。因为支付对个人开发者尤其是学生来说不太友好。因此,自己折腾两天
- 在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等。如果你想监控某一个线程池的执行状态,线程池执行类
- 相信有些同学跟我一样,曾经对这个问题很疑惑。在网上也看了一些别人说的观点,评论不一。有说有值传递和引用传递两种,也有说只有值传递的,这里只说
- @[toc]在之前的文章中松哥和小伙伴们聊过,正在执行的流程信息是保存在以 ACT_RU_ 为前缀的表中,执行完毕的流程
- 可以使用 graphics2D 类提供的 shear(
- 引言在前面的内容中,我们先是一一介绍了Collection集合中都有哪些种类的集合,并且详细地讲解了List集合中的相关知识,那么今天我们来
- /给三个整数从小到大排序并求和及其平均值//其中,三个待求整数及其排序的结果由引用参数传递;其和由输出参数传递;平均值由返回值返回。//在M
- 上一篇JavaMail入门第三篇 发送邮件中,我们学会了如何用JavaMail API提供的Transport类发送邮件,同样,JavaMa
- 场景网站智能问答场景,需要对多个分类查询,结果聚合展示由于每种分类都有自己的业务逻辑,有的需要查询数据库中间库,有的需要查询elastics
- resultMap的Colum和property属性1: resultMap标签当我们的数据库字段与实体类的属性不一致时,就需要使用该标签进
- java @Value("${}")获取不到配置文件中值1、property.yml配置spring: ma
- 前言在上一篇中,我们初步了解了Sentinel的基本概念,以及其有关限流方面的基础理论,本篇将通过简单的与框架进行整合,看看Sentinel
- java 二分法算法的实例1、前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序2、原理:将数组分为三部分,依次是
- 前言:在工作中一次排查慢接口时,查到了一个函数耗时较长,最终定位到是通过 List 去重导致的。由于测试环境还有线上早期数据较少,这个接口的
- 前言将采用slf+log4j2方式进行打印日志,以下用两种方式,一种基于maven的springboot2,一种jdk6,普通jar包的sp
- 一、为什么按值调用和按引用调用?方法或函数可以通过两种方式调用。一种是按值调用,另一种是按引用调用,这两种方式通常根据作为输入或参数传递给它
- 本文实例讲述了C#实现动态生成静态页面的类。分享给大家供大家参考,具体如下:动态生成静态页面有许多好处,比如生成html网页有利于被搜索引擎
- 实践过程效果代码public partial class Form1 : Form {