一个实用的HTTP代理程序设计与实现

合集下载

HTTP代理原理及实现

HTTP代理原理及实现

HTTP代理原理及实现普通代理第⼀种 Web 代理原理特别简单:下⾯这张图⽚来⾃于《HTTP 权威指南》,直观地展⽰了上述⾏为:假如我通过代理访问 A ⽹站,对于 A 来说,它会把代理当做客户端,完全察觉不到真正客户端的存在,这实现了隐藏客户端 IP 的⽬的。

当然代理也可以修改 HTTP 请求头部,通过X-Forwarded-IP这样的⾃定义头部告诉服务端真正的客户端 IP。

但服务器⽆法验证这个⾃定义头部真的是由代理添加,还是客户端修改了请求头,所以从 HTTP 头部字段获取IP 时,需要格外⼩⼼。

给浏览器显式的指定代理,需要⼿动修改浏览器或操作系统相关设置,或者指定 PAC(Proxy Auto-Configuration,⾃动配置代理)⽂件⾃动设置,还有些浏览器⽀持WPAD(Web Proxy Autodiscovery Protocol,Web 代理⾃动发现协议)。

显式指定浏览器代理这种⽅式⼀般称之为正向代理,浏览器启⽤正向代理后,会对 HTTP 请求报⽂做⼀些修改,来规避⽼旧代理服务器的⼀些问题,还有⼀种情况是访问 A ⽹站时,实际上访问的是代理,代理收到请求报⽂后,再向真正提供服务的服务器发起请求,并将响应转发给浏览器。

这种情况⼀般被称之为反向代理,它可以⽤来隐藏服务器 IP 及端⼝。

⼀般使⽤反向代理后,需要通过修改 DNS 让域名解析到代理服务器 IP,这时浏览器⽆法察觉到真正服务器的存在,当然也就不需要修改配置了。

反向代理是 Web 系统最为常见的⼀种部署⽅式,例如本博客就是使⽤ Nginx 的proxy_pass功能将浏览器请求转发到背后的 Node.js 服务。

了解完第⼀种代理的基本原理后,我们⽤ Node.js 实现⼀下它。

只包含核⼼逻辑的代码如下:以上代码运⾏后,会在本地8888端⼝开启 HTTP 代理服务,这个服务从请求报⽂中解析出请求 URL 和其他必要参数,新建到服务端的请求,并把代理收到的请求转发给新建的请求,最后再把服务端响应返回给浏览器。

Java实现http代理服务器

Java实现http代理服务器

Java实现http代理服务器 Java实现http代理服务器本⽂连接:gitee:默认端⼝:8888javac RuphyHttpProxy.javajava RuphyHttpProxy 11111代码如下://package me.muphy.servicce;import java.io.Closeable;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import .ServerSocket;import .Socket;import java.util.concurrent.CountDownLatch;import java.util.concurrent.TimeUnit;import java.util.regex.Matcher;import java.util.regex.Pattern;/*** http代理*/public class RuphyHttpProxy extends Thread {private final ServerSocket server;private final int port;public RuphyHttpProxy(int port) throws IOException {this.port = port;server = new ServerSocket(port);System.out.println("代理端⼝:" + this.port);}public static void main(String[] args) throws IOException {int port = 8888;if (args != null && args.length > 0 && args[0].matches("\\d+")) {port = Integer.parseInt(args[0]);}new RuphyHttpProxy(port).start();}@Overridepublic void run() {// 线程运⾏函数while (true) {try {Socket client = server.accept();//使⽤线程处理收到的请求new HttpConnectThread(client).start();} catch (Exception e) {e.printStackTrace();}}}/*** 新连接处理线程*/private static class HttpConnectThread extends Thread {private Socket client;private Socket server = null;private String host = null;private int port = 80;private int clientReadLength = 0;byte clientInputBuffer[] = new byte[1024 * 1024 * 4];private DataInputStream clientInputStream = null; //客户端输⼊流private DataInputStream serverInputStream = null; //服务端输⼊流private DataOutputStream clientOutputStream = null; //客户端输出流private DataOutputStream serverOutputStream = null; //服务端输出流private long createTime = System.currentTimeMillis();private String clientInputString = null;public HttpConnectThread(Socket client) {this.client = client;}@Overridepublic void run() {try {clientInputStream = new DataInputStream(client.getInputStream());clientOutputStream = new DataOutputStream(client.getOutputStream());if (clientInputStream != null && clientOutputStream != null) {clientReadLength = clientInputStream.read(clientInputBuffer, 0, clientInputBuffer.length); // 从客户端读数据if (clientReadLength > 0) { // 读到数据clientInputString = new String(clientInputBuffer, 0, clientReadLength);if (clientInputString.contains("\n")) {clientInputString = clientInputString.substring(0, clientInputString.indexOf("\n"));}if (clientInputString.contains("CONNECT ")) {parseServerHost("CONNECT ([^ ]+) HTTP/");} else if (clientInputString.contains("http://") && clientInputString.contains("HTTP/")) {// 从所读数据中取域名和端⼝号parseServerHost("http://([^/]+)/");}if (host != null) {server = new Socket(host, port);// 根据读到的域名和端⼝号建⽴套接字serverInputStream = new DataInputStream(server.getInputStream());serverOutputStream = new DataOutputStream(server.getOutputStream());if (serverInputStream != null && serverOutputStream != null && server != null) {if (clientInputString.contains("CONNECT ")) {doConnect();return;}doRequest();return;}}}} catch (Exception e) {e.printStackTrace();}IOUtils.close(serverInputStream, serverOutputStream, server, clientInputStream, clientOutputStream, client);}/*** 解析主机地址** @param regExp*/private void parseServerHost(String regExp) {Pattern pattern = pile(regExp);Matcher matcher = pattern.matcher(clientInputString + "/");if (matcher.find()) {host = matcher.group(1);if (host.contains(":")) {port = Integer.parseInt(host.substring(host.indexOf(":") + 1));host = host.substring(0, host.indexOf(":"));}}}/*** 处理请求** @throws IOException*/private void doRequest() throws IOException, InterruptedException {serverOutputStream.write(clientInputBuffer, 0, clientReadLength);serverOutputStream.flush();final CountDownLatch latch;if (clientInputString.contains("POST ")) {latch = new CountDownLatch(2);// 建⽴线程 , ⽤于从内⽹读数据 , 并返回给外⽹new HttpChannel(clientInputStream, serverOutputStream, latch).start();} else {latch = new CountDownLatch(1);}// 建⽴线程 , ⽤于从外⽹读数据 , 并返回给内⽹new HttpChannel(serverInputStream, clientOutputStream, latch).start();latch.await(120, TimeUnit.SECONDS);IOUtils.close(serverInputStream, serverOutputStream, server, clientInputStream, clientOutputStream, client);System.out.println("请求地址:" + clientInputString + ",耗时:" + (System.currentTimeMillis() - createTime) + "ms"); }/*** 处理连接请求** @return*/private void doConnect() throws IOException, InterruptedException {String ack = "HTTP/1.0 200 Connection established\r\n";ack = ack + "Proxy-agent: proxy\r\n\r\n";clientOutputStream.write(ack.getBytes());clientOutputStream.flush();final CountDownLatch latch = new CountDownLatch(2);// 建⽴线程 , ⽤于从外⽹读数据 , 并返回给内⽹new HttpChannel(serverInputStream, clientOutputStream, latch).start();// 建⽴线程 , ⽤于从内⽹读数据 , 并返回给外⽹new HttpChannel(clientInputStream, serverOutputStream, latch).start();latch.await(120, TimeUnit.SECONDS);IOUtils.close(serverInputStream, serverOutputStream, server, clientInputStream, clientOutputStream, client);}}/*** 流通道处理线程*/private static class HttpChannel extends Thread {private final CountDownLatch countDownLatch;private final DataInputStream in;private final DataOutputStream out;public HttpChannel(DataInputStream in, DataOutputStream out, CountDownLatch countDownLatch) {this.in = in;this.out = out;this.countDownLatch = countDownLatch;}@Overridepublic void run() {byte buf[] = new byte[10240];try {while ((len = in.read(buf, 0, buf.length)) != -1) { out.write(buf, 0, len);out.flush();}} catch (Exception e) {e.printStackTrace();} finally {IOUtils.close(in, out);countDownLatch.countDown();}}}/*** 流⼯具类*/private static class IOUtils {/*** 关闭所有流*/private static void close(Closeable... closeables) {if (closeables != null) {for (int i = 0; i < closeables.length; i++) {if (closeables[i] != null) {try {closeables[i].close();} catch (IOException e) {e.printStackTrace();}}}}}}}。

如何实现高效的HTTP代理服务器

如何实现高效的HTTP代理服务器

如何实现高效的HTTP代理服务器在现代互联网时代,HTTP代理服务器已经成为了一个必不可少的网络工具。

HTTP代理服务器不仅可以有效地提高网络访问速度,还可以保护用户的隐私和安全,成为了网络工作中不可缺少的一环。

但是,要实现一个高效的HTTP代理服务器,并不是一件简单的工作。

本文将从以下几个方面探讨如何实现高效的HTTP 代理服务器。

一、选择合适的服务器HTTP代理服务器的选择是非常重要的,因为服务器的硬件配置和带宽决定了代理服务器的处理能力。

选择合适的服务器,可以有效地提高HTTP代理服务器的转发速度和可靠性。

对于HTTP 代理服务器来说,硬件配置最好能够满足以下几个条件:1、高性能的处理器和内存HTTP代理服务器会处理大量的请求和响应,需要有一个高性能的处理器和足够大的内存来处理这些请求。

选择多核、高频的处理器和足够大的内存,能够提高HTTP代理服务器的转发速度和响应时间。

2、高速的网络接口HTTP代理服务器需要有一个高速、可靠的网络接口,以便快速地转发请求和响应。

选择10Gbps以上的网络接口,能够更好地保证代理服务器的转发速度和可靠性。

3、高速的硬盘存储HTTP代理服务器需要有足够的硬盘容量和高速的存储读写速度,以便缓存请求和响应。

选择高速的SSD硬盘,能够提高代理服务器的响应时间和性能。

二、优化网络传输在实现HTTP代理服务器时,应该注意网络传输的优化。

网络传输的优化包括以下几个方面:1、使用压缩算法HTTP代理服务器可以使用压缩算法,将数据压缩后再传输。

这样能够减少数据传输时的宽带占用率,提高网络传输速度。

目前比较常见的压缩算法有Gzip和Deflate。

2、使用缓存技术HTTP代理服务器可以使用缓存技术,将请求和响应缓存在本地,下次请求时直接从缓存中读取数据。

这样可以减少网络传输的次数,提高网络传输速度。

3、限制带宽使用HTTP代理服务器可以设置带宽限制,以限制网络传输时的宽带占用率。

编写了一个HTTP高匿代理

编写了一个HTTP高匿代理

1. 编写了一个HTTP高匿代理本以为编写http代理和上一篇的端口转发差不多的,结果实际一编写起来发现要复杂的多。

怎么回事呢,就在于要手动解析http协议。

说简单点吧,如果直接用ie上一个网站,用sniffe一看http请求头是这样的。

GET / HTTP/1.1Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/QVOD, application/QVOD, */* Accept-Language: zh-CNUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)Accept-Encoding: gzip, deflateHost: Connection: Keep-AliveCookie: xxxxxxxxx但是如果用代理就变成了这样GET / HTTP/1.1Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/QVOD, application/QVOD, */* Accept-Language: zh-CNUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)Accept-Encoding: gzip, deflateHost: Proxy-Connection: Keep-AliveCookie: xxxxxxxxx区别就在这里,用代理get那地方会把完整url写上,而且Connection加上了proxy标志,其他一样。

一个实用的HTTP代理程序设计与实现

一个实用的HTTP代理程序设计与实现

一个实用的HTTP代理程序设计与实现HTTP代理程序是一种常见的网络应用程序,它作为中介,将客户端请求转发给目标服务器,并将服务器的响应传递回客户端。

代理服务器在实际应用中具有许多用途,例如提供缓存功能、限制对一些网站或资源的访问、提供负载均衡等。

设计一个实用的HTTP代理程序可以分为以下几个步骤:1.建立TCP连接:当客户端发送一个HTTP请求到代理服务器时,代理服务器需要解析HTTP请求报文中的目标服务器地址和端口号,并建立TCP连接。

2.解析请求:代理服务器需要解析HTTP请求报文,提取出HTTP方法、URL、请求头部以及请求体等信息。

3.检查缓存:代理服务器可以实现缓存功能,检查请求URL是否命中缓存。

如果命中缓存,则直接返回缓存内容;否则,继续处理请求。

4.转发请求:代理服务器将从客户端接收到的HTTP请求报文转发给目标服务器。

在转发请求之前,代理服务器可以修改请求报文,例如更改请求头部、添加代理相关信息等。

5.接收响应:代理服务器接收目标服务器的响应,包括响应头部和响应体等信息。

6.缓存响应:代理服务器可以缓存从目标服务器接收到的响应,以便后续的相同请求可以直接从缓存返回数据。

7.返回响应:代理服务器将目标服务器的响应返回给客户端,同时可以对响应进行修改,例如更改响应头部、压缩响应内容等。

8.断开连接:当响应返回给客户端后,代理服务器可以关闭与目标服务器的TCP连接,同时等待下一个客户端请求的到来。

在实现HTTP代理程序时,需要注意以下几点:1.并发处理:代理服务器可能会同时接收多个客户端的请求,因此需要采用多线程或多进程的方式处理请求,以提高并发处理能力。

2.鉴权认证:代理服务器可以对客户端进行鉴权认证,以确保只有授权用户可以使用代理服务。

3.日志记录:代理服务器可以记录用户的请求和响应信息,以便进行排错和性能优化。

4.安全性考虑:代理服务器需要防止恶意用户通过代理绕过安全限制,因此可以实施一些安全策略,例如限制访问特定URL、防止跨站脚本攻击等。

Java实现HTTP代理服务器

Java实现HTTP代理服务器

Java实现HTTP代理服务器Java 实现HTTP代理服务器1. 主服务,⽤来侦听端⼝:package org.javaren.proxy;import .ServerSocket;import .Socket;publicclassSocketProxy{/*** @param args*/publicstaticvoid main(String[] args)throwsException{ServerSocket serverSocket =newServerSocket(8888);while(true){Socket socket =null;try{socket = serverSocket.accept();newSocketThread(socket).start();}catch(Exception e){e.printStackTrace();}}}}2. 核⼼代码,处理链接的代理线程,内部设计了Socket的认证:package org.javaren.proxy;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .Socket;publicclassSocketThreadextendsThread{privateSocket socketIn;privateInputStream isIn;privateOutputStream osIn;//privateSocket socketOut;privateInputStream isOut;privateOutputStream osOut;publicSocketThread(Socket socket){this.socketIn = socket;}privatebyte[] buffer =newbyte[4096];privatestaticfinalbyte[] VER ={0x5,0x0};privatestaticfinalbyte[] CONNECT_OK ={0x5,0x0,0x0,0x1,0,0,0,0,0,0};publicvoid run(){try{System.out.println("\n\na client connect "+ socketIn.getInetAddress()+":"+ socketIn.getPort());isIn = socketIn.getInputStream();osIn = socketIn.getOutputStream();int len = isIn.read(buffer);System.out.println("< "+ bytesToHexString(buffer,0, len));osIn.write(VER);osIn.flush();System.out.println("> "+ bytesToHexString(VER,0, VER.length));len = isIn.read(buffer);System.out.println("< "+ bytesToHexString(buffer,0, len));// 查找主机和端⼝String host = findHost(buffer,4,7);int port = findPort(buffer,8,9);System.out.println("host="+ host +",port="+ port);socketOut =newSocket(host, port);isOut = socketOut.getInputStream();osOut = socketOut.getOutputStream();//for(int i =4; i <=9; i++){CONNECT_OK[i]= buffer[i];}osIn.write(CONNECT_OK);osIn.flush();System.out.println("> "+ bytesToHexString(CONNECT_OK,0, CONNECT_OK.length));SocketThreadOutputout=newSocketThreadOutput(isIn, osOut); out.start();SocketThreadInputin=newSocketThreadInput(isOut, osIn);in.start();out.join();in.join();}catch(Exception e){System.out.println("a client leave");}finally{try{if(socketIn !=null){socketIn.close();}}catch(IOException e){e.printStackTrace();}}System.out.println("socket close");}publicstaticString findHost(byte[] bArray,intbegin,intend){StringBuffer sb =newStringBuffer();for(int i =begin; i <=end; i++){sb.append(Integer.toString(0xFF& bArray[i]));sb.append(".");}sb.deleteCharAt(sb.length()-1);return sb.toString();}publicstaticint findPort(byte[] bArray,intbegin,intend){int port =0;for(int i =begin; i <=end; i++){port <<=16;port += bArray[i];}return port;}// 4A 7D EB 69// 74 125 235 105publicstaticfinalString bytesToHexString(byte[] bArray,intbegin,intend){ StringBuffer sb =newStringBuffer(bArray.length);String sTemp;for(int i =begin; i <end; i++){sTemp =Integer.toHexString(0xFF& bArray[i]);if(sTemp.length()<2)sb.append(0);sb.append(sTemp.toUpperCase());sb.append(" ");}return sb.toString();}}3. 读取线程,负责外⾯读数据,写⼊到请求端:package org.javaren.proxy;/*** * 从外部读取,向内部发送信息*/import java.io.InputStream;import java.io.OutputStream; publicclassSocketThreadInputextendsThread{privateInputStream isOut;privateOutputStream osIn;publicSocketThreadInput(InputStream isOut,OutputStream osIn){this.isOut = isOut;this.osIn = osIn;}privatebyte[] buffer =newbyte[409600];publicvoid run(){try{int len;while((len = isOut.read(buffer))!=-1){if(len >0){System.out.println(newString(buffer,0, len));osIn.write(buffer,0, len);osIn.flush();}}}catch(Exception e){System.out.println("SocketThreadInput leave");}}}4. 写⼊线程,负责读取请求端数据,写⼊到⽬标端:package org.javaren.proxy;import java.io.InputStream;import java.io.OutputStream;/*** 从内部读取,向外部发送信息** @author zxq**/publicclassSocketThreadOutputextendsThread{privateInputStream isIn;privateOutputStream osOut;publicSocketThreadOutput(InputStream isIn,OutputStream osOut){ this.isIn = isIn;this.osOut = osOut;}privatebyte[] buffer =newbyte[409600];publicvoid run(){try{int len;while((len = isIn.read(buffer))!=-1){if(len >0){System.out.println(newString(buffer,0, len));osOut.write(buffer,0, len);osOut.flush();}}}catch(Exception e){System.out.println("SocketThreadOutput leave");}}}。

http服务器的设计与实现

http服务器的设计与实现

网络课程设计实验报告题目:HTTP服务器的设计及实现姓名:孙宇飞、庄好涛、王斌学院:信息科学技术学院专业:计算机科学与技术班级:计科82班学号:、、指导老师:叶锡君职称:副教授2011 年 9 月11日南京农业大学教务处制目录目录1.设计任务及要求................................................... 错误!未指定书签。

1.1设计目的................................. 错误!未指定书签。

1.2设计要求................................. 错误!未指定书签。

2.工作原理及设计方案............................................... 错误!未指定书签。

2.1工作原理................................. 错误!未指定书签。

2.2设计方案................................. 错误!未指定书签。

2.3开发环境................................. 错误!未指定书签。

2.4程序流程图............................... 错误!未指定书签。

2.5核心代码................................. 错误!未指定书签。

2.4.1主程序................................. 错误!未指定书签。

2.4.2请求处理函数........................... 错误!未指定书签。

2.4.3无法响应请求........................... 错误!未指定书签。

2.4.4404响应................................ 错误!未指定书签。

2.4.5判断是否是目录......................... 错误!未指定书签。

python实现简单http代理

python实现简单http代理

python实现简单http代理http 代理有什么⽤处?1,可以是插⼊ js ⼴告,某些 isp 就是这么⼲的,强插⼴告,现在 https 的⽹站越来越多了,插⼊不了。

2, ⽤来调试 app 或是别的程序,可以看到详细的 http 请求,响应,fiddler 这个软件也是做这个的,但它不开源。

使⽤ wireshark 抓包:GET http://localhost/logo.gif HTTP/1.1Host: localhostUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateDNT: 1Connection: keep-aliveUpgrade-Insecure-Requests: 1#或第 2 种GET http://localhost:8000/logo.gif HTTP/1.1Host: localhost:8000User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateDNT: 1Connection: keep-aliveUpgrade-Insecure-Requests: 1原理:http 1.1 也就是 tcp 连接,有 header 和 body ,更多复杂的细节这⾥不做介绍(session cookie 缓存等)下⾯使⽤ python 实现, listen 8000 端⼝,分析原始的请求⽹址的HOST 和端⼝,建⽴连接拿回数据转发。

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

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

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 .ServerSocket;import .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();}@Overridepublic 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 infofinal 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!");}}。

用VC++实现http代理

用VC++实现http代理

透过代理看世界用VC++实现http代理为了帮网友些个用http下载动画的程序,临时在网上翻了翻,看看有没有利用http代理来下载的例子。

结果,似乎很多人都愿意去转载一个有头无尾的例子,还美其名曰“我在查阅RFC文档和相关资料后,特总结一些TCP协议穿透代理服务器的程序片断,希望对大家有所帮助。

”如果真的想帮助大家,为什么不说的详细一些?无奈之下,自己去翻rfc文档,找了些资料,写了这个利用http代理来下载文件的资料代码如下:(1)一些基本变量SOCKET HTTPSocket; // 主socketstruct sockaddr_in SocketAddr; // address socketstruct sockaddr_in BindSocket; // for bindint m_nRecvTimeout; // recieve timeoutint m_nSendTimeout; // send timeoutWSADATA wsaData;// 要下载文件部分。

好像在BindSocket.sin_addr.s_addr = inet_addr (strHost);时,只能使用ip地址,所以了。

// 如果谁知道更好的方法,别忘了告诉我一下。

CString strHost="111.111.111.111 ";CString DownLoadAddress="/bbs/images/"; CString hostFile="logo.gif";int HttpPort=80;(2)一些函数,用来取得http头,和获取文件大小int GetFileLength(char *httpHeader){CString strHeader;int local;strHeader=(CString)httpHeader;local=strHeader.Find("Content-Length",0);local+=16;strHeader.Delete(0,local);local=strHeader.Find("\r");strHeader.SetAt(local,'\0');char temp[30];strcpy(temp,strHeader.GetBuffer(strHeader.GetLength()));return atoi(temp);}int GetHttpHeader(SOCKET sckDest,char *str){BOOL m_bResponsed=0;int m_nResponseHeaderSize;if(!m_bResponsed){char c = 0;int nIndex = 0;BOOL bEndResponse = FALSE;while(!bEndResponse && nIndex < 1024){recv(sckDest,&c,1,0);str[nIndex++] = c;if(nIndex >= 4){if(str[nIndex - 4] == '\r' && str[nIndex - 3] == '\n'&& str[nIndex - 2] == '\r' && str[nIndex - 1] == '\n')bEndResponse = TRUE;}}m_nResponseHeaderSize = nIndex;m_bResponsed = TRUE;}return m_nResponseHeaderSize;}(3)用来发送的部分void szcopy(char* dest,const char* src,int nMaxBytes){int i_cntr=0;while ((src[i_cntr]!='\0') || (i_cntr<nMaxBytes))dest[i_cntr]=src[i_cntr++];dest[i_cntr]='\0';}BOOL SocketSend(SOCKET sckDest,const char* szHttp){char szSendHeader[MAXHEADERLENGTH];int iLen=strlen(szHttp);szcopy(szSendHeader,szHttp,iLen);if(send (sckDest ,(const char FAR *)szSendHeader ,iLen ,0)==SOCKET_ERROR) {closesocket(sckDest);AfxMessageBox("Error when send");return FALSE;}return TRUE;}BOOL SocketSend(SOCKET sckDest,CString szHttp){int iLen=szHttp.GetLength();if(send (sckDest,szHttp,iLen,0)==SOCKET_ERROR){closesocket(sckDest);AfxMessageBox("Error when send");return FALSE;}return TRUE;}(4)用于连接的函数这里是做了一些连接用的操作,分了两种情况1)如果没有使用代理,则直接连到你指定的计算机2)如果使用了代理,则直接连到代理BOOL CDLAngelDlg::ConnectHttp(){message="正在建立连接\n";UpdateData(TRUE);if(m_combo=="HTTP") // m_combo 一个下拉条{HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);SocketAddr.sin_addr.s_addr = inet_addr (m_ProxyAddr);SocketAddr.sin_family=AF_INET;SocketAddr.sin_port=htons(atoi(m_Port));struct fd_set fdSet;struct timeval tmvTimeout={0L,0L};FD_ZERO(&fdSet);FD_SET(HTTPSocket, &fdSet);if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR){closesocket(HTTPSocket);AfxMessageBox("Error when select.");return 0;}if (connect(HTTPSocket, (const struct sockaddr *)&SocketAddr, sizeof(SocketAddr))==SOCKET_ERROR){message="\n代理连接失败\n";m_message.CleanText();m_message.AddText(message);return 0;}// 发送CONNCET请求令到代理服务器,用于和代理建立连接//代理服务器的地址和端口放在m_ProxyAddr,m_Port 里面CString temp;char tmpBuffer[1024];temp.Format("CONNECT %s:%s HTTP/1.1\r\nUser-Agent:MyApp/0.1\r\n\r\n",m_ProxyAddr,m_Port);if(!SocketSend(HTTPSocket,temp)){message="连接代理失败";return 0;}// 取得代理响应,如果连接代理成功,代理服务器将返回200 Connection established GetHttpHeader(HTTPSocket,tmpBuffer);temp=tmpBuffer;if(temp.Find("HTTP/1.0 200 Connection established",0)==-1){message="连接代理失败\n";return 0;}message="代理连接完成\n";m_message.AddText("代理连接完成\n");return 1; // ----------〉这里是应该注意的,连接到代理后,就可以返回了,不需要再连接网上的另外一台机,代理服务器会自动转发数据,所以,连接完代理就像连接到网上另外一台机一样}// 这个,是为了给其他代理做准备else if(m_combo=="Socks4"){MessageBox("请注意,现在无法使用代理功能!");}else if(m_combo=="Socks5"){MessageBox("请注意,现在无法使用代理功能!");}// 如果没有使用代理,就要连接到网上的另一台机// 准备socketHTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (HTTPSocket==INVALID_SOCKET){AfxMessageBox("Error when socket");return 0;}//设置超时struct linger zeroLinger;zeroLinger.l_onoff = 1;zeroLinger.l_linger = 0;if(setsockopt(HTTPSocket,SOL_SOCKET,SO_LINGER,(const char *)&zeroLinger,sizeof(zeroLinger))!=0){closesocket(HTTPSocket);AfxMessageBox("Error when setscokopt(LINGER)");return 0;}//设置接收超时if(setsockopt(HTTPSocket,SOL_SOCKET,SO_RCVTIMEO,(const char *)&m_nRecvTimeout,sizeof(m_nRecvTimeout))!=0){closesocket(HTTPSocket);AfxMessageBox("Error when setsockopt(RCVTIME).");return 0;}//设置发送超时if(setsockopt(HTTPSocket,SOL_SOCKET,SO_SNDTIMEO,(const char *)&m_nSendTimeout,sizeof(m_nSendTimeout))!=0){closesocket(HTTPSocket);AfxMessageBox("Error when setsockopt(SNDTIMEO).");return 0;}SocketAddr.sin_addr.s_addr = htonl (INADDR_ANY);SocketAddr.sin_family=AF_INET;// 进行端口绑定if (bind (HTTPSocket,(const struct sockaddr FAR *)&SocketAddr,sizeof(SocketAddr))==SOCKET_ERROR){closesocket(HTTPSocket);AfxMessageBox("Error when bind socket.");return 0;}//准备连接/// 准备连接信息BindSocket.sin_addr.s_addr = inet_addr (strHost);BindSocket.sin_family=AF_INET;BindSocket.sin_port=htons(HttpPort);struct fd_set fdSet;struct timeval tmvTimeout={0L,0L};FD_ZERO(&fdSet);FD_SET(HTTPSocket, &fdSet);if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR) {closesocket(HTTPSocket);AfxMessageBox("Error when select.");return 0;}// 连接if (connect(HTTPSocket, (const struct sockaddr *)&BindSocket, sizeof(BindSocket))==SOCKET_ERROR){AfxMessageBox("第一次连接失败,准备第二次连接");if (connect(HTTPSocket,(const struct sockaddr *)&BindSocket,sizeof(BindSocket))==SOCKET_ERROR){closesocket(HTTPSocket);AfxMessageBox("连接失败");return 0;}}message="连接完成\n";return 1;}(5)发送http请求,为下载数据进行准备int CDLAngelDlg::SendHttpHeader(){//进行下载CString temp;BOOL bReturn;char tmpBuffer[MAXBLOCKSIZE];///第1行:方法,请求的路径,版本temp="GET "+DownLoadAddress+hostFile+" HTTP/1.0\r\n"; bReturn=SocketSend(HTTPSocket,temp);if(!bReturn){message="发送请求失败";return 0;}///第2行:主机temp="Host "+strHost+"\r\n";bReturn=SocketSend(HTTPSocket,temp);if(!bReturn){message="发送请求失败";return 0;}///第3行:接收的数据类型bReturn=SocketSend(HTTPSocket,"Accept: */*\r\n");if(!bReturn){message="发送请求失败";return 0;}///第4行:temp=DownLoadAddress;temp.Insert(0,"Referer ");temp+="\r\n";bReturn=SocketSend(HTTPSocket,temp);if(!bReturn){message="发送请求失败";return 0;}///第5行:浏览器类型bReturn=SocketSend(HTTPSocket,"User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DTS Agent;)\r\n");if(!bReturn){message="发送请求失败";return 0;}///第6行:连接设置,保持// SocketSend(HTTPSocket,"Connection:Keep-Alive\r\n");///第7行:Cookie.bReturn=SocketSend(HTTPSocket,"Cache-Control: no-cache\r\n");if(!bReturn){message="发送请求失败";return 0;}bReturn=SocketSend(HTTPSocket,"Proxy-Connection: Keep-Alive\r\n"); if(!bReturn){message="发送请求失败";return 0;}/// 续传Range是要下载的数据范围,对续传很重要if(continueFlag){temp.Format("Range: bytes=%d- \r\n",conLength);bReturn=SocketSend(HTTPSocket,temp);if(!bReturn){message="发送请求失败";return 0;}}///最后一行:空行bReturn=SocketSend(HTTPSocket,"\r\n");if(!bReturn){message="发送请求失败";return 0;}///取得http头int i;i=GetHttpHeader(HTTPSocket,tmpBuffer);if(!i){message="获取HTTP头出错";return 0;}//如果取得的http头含有404等字样,则表示连接出问题 temp=tmpBuffer;if(temp.Find("404")!=-1){return 0;}// 得到待下载文件的大小filelength=GetFileLength(tmpBuffer);return 1;}这样,就连接到网上的另一台机了,如何下载数据,不用多说了吧while((num!=SOCKET_ERROR) && (num!=0)){num=recv (HTTPSocket,(char FAR *)tmpBuffer,(MAXBLOCKSIZE-1),0);file.Write(tmpBuffer,num);if(ExitFlag){file.Close();closesocket(HTTPSocket);DownComplete=1;m_message.CleanText();m_message.ShowColorText(RGB(128,128,0),DLCompleteMes);m_progress.ShowWindow(SW_HIDE);m_stopDownload.ShowWindow(SW_HIDE);_endthread();}}基本就是这样了,本人写程序水平也不是很高,这个程序还是可以用的。

计算机网络-实验1-HTTP代理服务器的设计与实现

计算机网络-实验1-HTTP代理服务器的设计与实现

实验1:HTTP代理服务器的设计与实现
1.实验目的
熟悉并掌握 Socket 网络编程的过程与技术;深入理解 HTTP 协议,掌握 HTTP 代理服务器的基本工作原理;掌握 HTTP 代理服务器设计与编程实现的基本技能。

2.实验环境
接入Internet的实验主机;
Windows xp或Windows7/8;
开发语言:python
3.实验内容
(1) 设计并实现一个基本 HTTP 代理服务器。

要求在指定端口(例如8080)接收来自客户的 HTTP 请求并且根据其中的 URL 地址访问该地址所指向的 HTTP 服务器(原服务器),接收 HTTP 服务器的响应报文,并将响应报文转发给对应的客户进行浏览。

(2) 扩展 HTTP 代理服务器,支持如下功能:
a) 网站过滤:允许/不允许访问某些网站;
b) 网站引导:将用户对某个网站的访问引导至一个模拟网站(钓鱼)。

4.实验步骤
(1)浏览器使用代理
为了使浏览器访问网址时通过代理服务器,必须进行相关设置,以IE 浏览器设置为例:打开浏览器工具浏览器选项连接局域网设置代理服务器。

本实验中,设定代理服务器地址为:127.0.0.1:12000,即本机的12000端口。

(2)网站过滤/网站引导:本实验中将两个功能结合——URL含有指定的网址时,自动跳转到一个钓鱼网站上。

首先,设定专用函数识别禁止访问的网站:
然后,根据匹配的结果,确定访问的网址:
当使用者试图访问禁止的网址时,将其访问请求转向WPKG:
5.实验结果:
(1)访问允许的网站
(2)访问禁止的网站。

http代理的实现原理

http代理的实现原理

http代理的实现原理
http代理的实现原理主要涉及到以下几个方面:
1. 客户端与代理服务器的建立连接:客户端需要向代理服务器发送请求,建立起连接。

客户端将请求发送给代理服务器的
IP地址和端口号。

2. 代理服务器接收请求:代理服务器接收到客户端发送的请求后,根据请求中的目标服务器地址和端口号,将请求转发给目标服务器。

3. 代理服务器与目标服务器建立连接:代理服务器与目标服务器建立连接,将客户端的请求发送给目标服务器。

4. 目标服务器处理请求并返回响应:目标服务器接收到代理服务器发送的请求后,根据请求的内容进行处理,并将处理结果封装成响应发送给代理服务器。

5. 代理服务器接收响应并返回给客户端:代理服务器接收到目标服务器发送的响应后,将响应的内容封装成HTTP响应的格式,并将响应返回给客户端。

通过以上的步骤,客户端可以通过代理服务器与目标服务器进行通信,实现HTTP代理的功能。

代理服务器作为一个中间人,接收来自客户端的请求并转发给目标服务器,然后再将目标服务器的响应返回给客户端。

这样的设计可以提高网络通信的效
率,加快数据传输的速度。

同时,代理服务器还可以实现一些额外的功能,例如缓存响应、过滤内容、负载均衡等。

一个实用的HTTP代理程序设计与实现

一个实用的HTTP代理程序设计与实现

一个实用的HTTP代理程序设计与实现摘要:本文介绍了HTTP代理服务器基本工作原理、代理服务器的总体设计框架和其中采用的用以提高性能的关健技术、进程池技术和缓存机制以及核心模块的具体实现流程,最后提出了一种实用的HTTP代理服务器的设计方案。

关键词:代理服务器; 进程池; 缓存机制Abstract:The design and implementation of HTTP proxy server with high performance are described. First, the basic mechanism of HTTP proxy server is introduced and then, the whole framework of proxy server and the key techniques process pool and cache technique are presented which are adopted to improve performance. Finally, the implementations of core modules are given.Key words: proxy server; process pool; cache mechanism目录第一章前言 (2)第二章HTTP原理与代理模型的设计 (3)2.1 HTTP协议 (3)2.2 HTTP代理模型 (3)2.3 模型的实现 (4)2.4 优化的代理技术 (7)2.4.1 身份认证 (7)2.4.2 Cache技术 (8)第三章总体设计 (10)3.1框架结构 (10)3.2关键技术 (10)3.2.1进程池管理 (10)3.2.2缓存管理 (12)第四章核心模块的实现 (14)4.1主守护进程的实现 (14)4.2代理服务模块的实现 (14)4.3缓存管理进程的实现 (16)结语 (17)参考文献: (17)第一章前言随着Internet与Intranet的飞速发展,作为连接Internet与Intranet的的桥梁,代理服务器在实际应用中发挥着极其重要的作用。

Python网络请求模块实现HTTP请求

Python网络请求模块实现HTTP请求

Python网络请求模块实现HTTP请求在Python编程领域中,网络请求是一项非常重要的功能。

通过HTTP请求,我们可以与远程服务器进行数据交互,获取所需的信息。

Python提供了多种网络请求模块,如requests、urllib等,这些模块使得我们能够轻松地实现各种类型的HTTP请求。

本文将介绍如何使用Python中的网络请求模块来实现HTTP请求,并探讨它们的优缺点以及适用场景。

1. 使用requests模块发送HTTP请求requests是Python中最受欢迎的HTTP库之一,它简单易用且功能强大。

通过requests模块,我们可以发送GET、POST等各种类型的HTTP请求,并处理服务器响应。

以下是一个简单的示例,演示了如何使用requests发送一个GET请求:示例代码star:编程语言:pythonimport requestsurl = '对应网址'response = requests.get(url)print(response.status_code)print(response.text)示例代码end在上面的代码中,我们首先导入了requests模块,然后指定了要访问的URL地址,并使用get()方法发送了一个GET请求。

最后打印出了服务器返回的状态码和响应内容。

2. 使用urllib模块发送HTTP请求除了requests模块外,Python标准库中的urllib模块也提供了发送HTTP请求的功能。

虽然相对于requests来说使用稍显繁琐,但在某些情况下仍然是一个不错的选择。

以下是一个使用urllib发送GET请求的示例:示例代码star:编程语言:pythonfrom urllib import requesturl = '对应网址'response = request.urlopen(url)print(response.getcode())print(response.read().decode('utf-8'))示例代码end在上面的代码中,我们使用了urllib.request.urlopen()方法来发送一个GET请求,并通过getcode()方法获取状态码,通过read().decode('utf-8')方法获取响应内容。

用C#实现Http代理服务器

用C#实现Http代理服务器

用C#实现Http代理服务器
陈东
【期刊名称】《电脑编程技巧与维护》
【年(卷),期】2004(000)004
【摘要】一、引言.随着Internet的高速发展,代理服务器日益成为企业及家庭用户连接内部网络与Internet的重要工具。

代理服务器在本地浏览器和远端Web 服务器之间转发命令(请求与应答命令)和数据(信息流),在内外部网络间起桥接作用,用一个公用IP地址提供给多个客户端用户,以同时访问Internet,从而大大减少上网费用,并可延伸出网络管理、网络监控等多种用途。

本文介绍用C#实现Http协议代理服务器的方法并提供经验证的Http协议代理服务器实用程序。

【总页数】6页(P69-74)
【作者】陈东
【作者单位】无
【正文语种】中文
【中图分类】TP31
【相关文献】
1.基于HTTP的隐藏型代理服务器实现 [J], 侯宇飞
2.基于Java多线程的HTTP代理服务器的研究与实现 [J], 唐志军;朱宇光;彭勤革
3.一种HTTP代理服务器的设计与实现 [J], 胡居成;李侠林;黄皓
4.在C#语言下通过HTTPS协议实现SOAP报文操作 [J], 廖文建;
5.在C#语言下通过HTTPS协议实现SOAP报文操作 [J], 廖文建
因版权原因,仅展示原文概要,查看原文内容请购买。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一个实用的HTTP代理程序设计与实现摘要:本文介绍了HTTP代理服务器基本工作原理、代理服务器的总体设计框架和其中采用的用以提高性能的关健技术、进程池技术和缓存机制以及核心模块的具体实现流程,最后提出了一种实用的HTTP代理服务器的设计方案。

关键词:代理服务器; 进程池; 缓存机制Abstract:The design and implementation of HTTP proxy server with high performance are described. First, the basic mechanism of HTTP proxy server is introduced and then, the whole framework of proxy server and the key techniques process pool and cache technique are presented which are adopted to improve performance. Finally, the implementations of core modules are given.Key words: proxy server; process pool; cache mechanism目录第一章前言 (2)第二章HTTP原理与代理模型的设计 (3)2.1 HTTP协议 (3)2.2 HTTP代理模型 (3)2.3 模型的实现 (4)2.4 优化的代理技术 (7)2.4.1 身份认证 (7)2.4.2 Cache技术 (8)第三章总体设计 (10)3.1框架结构 (10)3.2关键技术 (10)3.2.1进程池管理 (10)3.2.2缓存管理 (12)第四章核心模块的实现 (14)4.1主守护进程的实现 (14)4.2代理服务模块的实现 (14)4.3缓存管理进程的实现 (16)结语 (17)参考文献: (17)第一章前言随着Internet与Intranet的飞速发展,作为连接Internet与Intranet的的桥梁,代理服务器在实际应用中发挥着极其重要的作用。

代理服务器(Proxy)是网络信息的中转站。

一般情况下,使用网络浏览器直接去链接其它Internet站点并取得网络信息时,须送出请求信写来得到应答,然后对方再把信息传送回来。

代理服务器是介于浏览器和Web服务器之间的一台服务器,有了它之后,浏览器不是直接到Web服务器去取回网页而是向代理服务器发出请求,请求信写会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。

而且,大部分代理服务器都具有缓冲的功能,就好像一个大的Cache,它不断将新取得数据包存到它本机的存储器上,如果浏览器所请求的数据在它本机的存储器上己经存在而且是最新的,那么它就不重新从Web服务器取数据,而直接将存储器上的数据传送给用户的浏览器,这样就能显著提高浏览速度和效率。

代理服务器不仅可以实现提高浏览速度和效率的功能,它还可以实现网络的安全过滤、流量控制(减少Internet使用费用)、用户管理等功能,因此它既是一种网络防火墙技术,同时也可以解决许多单位连接Internet引起IP地址不足的问题。

将代理服务器的这些功能应用在多媒体教室中,可以方便地实现教师机对学生机的管理,下面就介绍一下该代理模型的设计与实现。

第二章HTTP原理与代理模型的设计2.1 HTTP协议HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。

当客户端请求一个Web页面时,它首先与服务器建立连接,连接成功后,它要将所请求的页面,所用的协议及版木,语言及版木,所能接受的MIME类型,编码类型以及连接状况等一些本地信息参数等交给服务器,Web服务器收到请求后,发回所交送页面的的信息的响应头信息,然后再发送页面内容信息,最后,双方断开连接。

HTTP的早期版木为HTTP/0.9},1982年,Tim Berners-Lee提出了HTTP/1.0,1997年形成HTTP/ 1.1,也就是现在普遍使用的协议。

HTTP/ 1.1在持续连接操作机制中实现流水方式,即客户端需要对同一服务器发出多个请求时,其请求的多数的Web页面都是由多部分组成(比如多张图片,声音),可用流水线方式加快速度。

流水机制就是指在客户机请求到Web页面时,搜索其中的图像链接和声音链接,然后再请求这些页面,即连续发出多个请求并等到这些请求发送完毕,再等待响应。

这样就大大节省了单独请求对响应的等待时间,使人们得到更快速的浏览。

而且HTTP-NG (Next Generation of HTTP)的建议己经提出。

2.2 HTTP代理模型根据HTTP协议规定,当客户端使用代理模式时,发送的请求命令格式如下: method http: //hostname/path/···/filename 例如:GET http: //.cm/。

当客户端同网络代理服务系统建立连接后,代理服务器将收到请求命令,这时代理服务器应该截取主机名部分进行域名解析,并同该主机建立连接,将去掉主机名部分的请求命令转发给它,等待它做出响应,然后将得到的响应转发给客户端,最后断开连接。

其模型如图2-1所示。

图2-1 带有Cache数据库的HTTP协议代理模型注:①客户连接代理服务器,并发出客户请求:②在本地Cache中无此资源时,连接到Internet;③从Internet上获得所请求的资源:④将客户所请求的资源发送给客户:②*代理服务系统检索Cache 数据库:③*如果客户请求的资源在数据库中,这直接将请求的资源发给代理服务器:2.3 模型的实现由于HTTP代理是典型的C/S模式,所以至少需要两个Socket(套接字)来实现客户与Web服务器的连接。

结合在多媒体教室巾的应用,具体过程如下:(1)代理服务器监听客户端的连接请求;(2)客户端连接到代理服务器,发送请求信息;(3)代理服务器解析客户端的发送过来的数据,确定服务类型(HTTP),服务器地址和端口号,确定是否是合法的IP和URL,确定是否在木地Cache库巾,是,则重定向,不是,则执行(4);(4)代理服务器连接远程Web服务器;(5)循环启动线程Server,该线程负责客户端,代理服务器和远程Web服务器之间数据的交互,交互完毕结束线程;(6)关闭server— field Socket(服务器端套接字),断开代理与web服务器的连接;(7)关闭client_ field Socket(客户端套接字),断开客户端与代理服务器的连接;其实现系统流程图如2所示。

图2-2 HTTP代理服务器系统实现流程图在系统设计中,为客户端和服务器各建一个Socket套接字client_ field和server_ field以来实现客户和Web服务器的连接。

由于在该代理系统操作中是要求用户主机和远端主机双向通信的,这样就要求对两个套接字描述符既能够读也能够写。

如果采用的是阻塞I/0的话,很有可能长时间阻塞在一个描述符上。

因此设计时在处理这个问题的时候调用了select()函数,这个函数允许执行I/O 多路转接。

其具体含义就是select()函数可以构造一个表,在这个表中包含了所有要用到的文件描述符。

然后可以调用一个函数,这个函数可以检测这些文件描述符的状态,当某个指定的)文件描述符准各好进行I/O操作时,此函数就返回,告知进程哪个文件描述符己经可以执行I/O操作了。

这样就避免了长时间的阻塞。

在调用select()函数实现多路I/O转接时,首先要声明一个新的文件描述符集:Fd - set rdfdset;然后调用FD- ZERO ()清空此文件描述符集的所有位,以免下面检测描述符位的时候返回错误结果:FD_ ZERO ( &rdfdset);然后调用FD_ SET( )在文件描述符集中设置所关心的位。

在该系统中,关心的就是分别与用户主机和远端主机连接的两个套接字描述符,所以执行这样的语句:FD_ SET (client_ field , &rdfdset) ;FD_SET (server_ f ield ,&rdfdset) ;然后调用select()返回描述符状态,此时描述符状态被存储进描述符集,也就是fd _ set数据结构中。

在该系统中,只关心两个套接字描述符是否可读,因此执行这样的select ()函数:Select (FD_ SETSIZE, &rdfdset, NULL, NULL ,NULL)那么在select ()返回后调用函数FD_ ISSET ()如果对应文件描述符的状态为“己准备好”(即描述符位为“1"),则FD IS-SET 0返回"1",否则返回"0"。

下面一段代码就实现从套接字client_ field用户主机)到套接字server_ field (远端主机)的无阻塞传输。

Char buf [1024]:int iolcn -0:if (FD_ ISSET( client_ field. &rdfdset)){if ( Iolen =read (client_ field, buff ,sizeof (buf)))<=0)break : //长度为0意味着连接中断write 9Server_ field. buf. iolen ): //缓冲区的内容发送至服务器端}而这一段代码则实现了反方向的无阻塞传输:if (FD_ ISSET( Server _field, &rdfdset)){if <((iolen =read( Server_ field, buf, sizeof buf ) ) )<=0)break;write( client field, buf, iolen );//缓冲区内容发送至客户端}这样就通过代理服务器实现了用户主机与远端主机之间的通信。

将该代理系统应用到多媒体教室中,学生机就相当于一个个客户机,教师机就相当于代理服务器。

当学生机发送请求时,教师机首先看其IP地址是否有权限访问Internet(学生机的IP权限可事先由教师设定),然后再看其请求的URL是否合法(不合法的URL事先存储在数据库中),如果是,再看其请求的URL是否在Cache库中,若在并且没有到达更新期限,则从硬盘中读出并显示在客户端;否则,连接到远程Web服务器并缓存相应的数据或更新Cache库。

这样,不仅提高了学生上网的速度,节约了带宽,而且,也提高了系统的安全性,方便了教师对学生的管理。

相关文档
最新文档