大可制作:QQ群:31564239(asp|jsp|php|mysql)

Java Gossip: 代理服务器

代理服务器的作用,就是作为连线来源端与连线目的端之间的桥梁,代理服务器的功能有很多种,有作为网页快取的代理服务器,有作为防火墙功能的代理服务器,有作为讯息过滤的代理服务器等等。

客户端 <---->  代理服务器  <---->  目的服务器

其实将代理服务器的功能简化至最基本时,其功能就是将连线来源端的讯息转接至连线目的端,而连线目的端的讯息转接至连线来源端,对连线来源端而言,代理服务器像是伺服端,对连线目的端而言,代理服务器像是客户端。

讯息在代理服务器时所作的处理,决定了代理服务器的种类,如果它将网页暂存在服务器本身的储存装置,并供客户端直接比对下载,它的作用就是网页代理伺服 器,如果它的作用在过滤进出代理服务器的讯息,它的作用就有些像是防火墙的功能(当然必须实现低阶的封包过滤才算真正是),您也可以设计一个代理服务器, 专门过滤掉网页上的广告部份。

下面这个程序即实现一个最简单的代理服务器功能,它将连线来源端的讯息转接至连线目的端,而连线目的端的讯息转接至连线来源端,为了简化程序逻辑,这个程序一次只能服务一个连线:
  • SimpleProxyServer.java
package onlyfun.caterpillar;

import java.io.*;
import java.net.*;

public class SimpleProxyServer {
public static void main(String[] args) {
String host; // 代理的对象主机
int remotePort; // 代理对象连接埠
int localPort; // 本机连接埠
BufferedReader reader;

try {
reader = new BufferedReader(
new InputStreamReader(System.in));

System.out.println("SimpleProxyServer v0.1");
System.out.print("代理的对象主机: ");
host = reader.readLine();
System.out.print("代理对象连接埠: ");
remotePort = Integer.parseInt(reader.readLine());
System.out.print("本机连接埠: ");
localPort = Integer.parseInt(reader.readLine());

runServer(host, remotePort, localPort);
}
catch(IOException e) {
System.err.println(e.toString());
}
}

public static void runServer(String host, int remotePort, int localPort) {
try {
System.out.printf("Proxy服务器启动...Port %d%n", localPort);
ServerSocket proxyServerSkt = new ServerSocket(localPort);
System.out.println("OK!");

while(true) {
System.out.println("倾听客户端.....");
Socket clientSkt = proxyServerSkt.accept();
System.out.printf("%s 连线..%n",
clientSkt.getInetAddress().toString());

// 客户端的来往讯息
final BufferedInputStream clientInputStream =
new BufferedInputStream(clientSkt.getInputStream());
PrintStream clientPrintStream =
new PrintStream(clientSkt.getOutputStream());

// 伺服端的来往讯息
final Socket serverSkt = new Socket(host, remotePort);
BufferedInputStream fromServerMsg = new BufferedInputStream(
serverSkt.getInputStream());
final PrintStream serverPrintStream = new
PrintStream(serverSkt.getOutputStream());

// 由客户端至服务器的讯息沟通线程
Thread client = new Thread() {
public void run() {
int read;
try {
while((read = clientInputStream.read()) != -1) {
serverPrintStream.write(read);
serverPrintStream.flush();
}
}
catch(IOException e) {}

// 中断至服务器的连线
try {
serverSkt.close();
}
catch(IOException e) {
System.err.println(e.toString());
}
}
};

client.start();

// 主线程为由服务器至客户端的讯息
int read;
try {
while((read = fromServerMsg.read()) != -1) {
clientPrintStream.write(read);
clientPrintStream.flush();
}
}
catch(IOException e) {
e.printStackTrace();
};

// 中断与客户端的连线
try {
clientSkt.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
catch(UnknownHostException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
}
}

您有几个方法可以测试这个程序,首先启动程序:
SimpleProxyServer v0.1
代理的对象主机: ptt.cc
代理对象连接埠: 23
本机连接埠: 23
Proxy服务器启动...Port 23..OK!
倾听客户端.....

范例在本机8888连接埠启动了代理服务器,代理的对象是ptt.cc,接下来您可以直接telnet localhost 23,本机所启动的代理服务器会帮您连线至ptt.cc,接下来的一切操作就与BBS操作相同了。

您也可以让它代理一个Web服务器,假设本机代理服务器连接埠也设定为8080,当使用浏览器键入http://localhost:8080/时,您会发现浏览器自动连接至代理的网页服务器。