本實(shí)例實(shí)現(xiàn)了一個(gè)代理服務(wù)器,實(shí)質(zhì)上是實(shí)現(xiàn)了一個(gè)代理服務(wù),部署在前文實(shí)現(xiàn)的通用服務(wù)器框架上。用戶需要指定目標(biāo)服務(wù)器的IP地址和端口,然后在瀏覽器中輸入本地網(wǎng)址,便可以訪問目標(biāo)服務(wù)器上的網(wǎng)頁。
代理服務(wù)作為一個(gè)服務(wù)部署在服務(wù)器框架上,必須實(shí)現(xiàn)book.net.GeneraServer$Service接口,實(shí)現(xiàn)它的serve方法。
當(dāng)客戶端請求代理服務(wù)時(shí),客戶端與代理服務(wù)之間會建立socket,代理服務(wù)收到請求后,會與目標(biāo)服務(wù)器建立Socket。
代理服務(wù)持有兩個(gè)Socket,它起中轉(zhuǎn)作用,將來自客戶端的請求轉(zhuǎn)發(fā)給服務(wù)器,來自服務(wù)器端的響應(yīng)消息轉(zhuǎn)發(fā)給客戶端,可以通過兩個(gè)線程分別處理請求消息的轉(zhuǎn)發(fā)和響應(yīng)消息的轉(zhuǎn)發(fā)。

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

/**
* 本類為支持多線程服務(wù)器框架的GeneralServer類提供了一個(gè)相關(guān)的服務(wù)Service,
* 使GeneralServer提供代理服務(wù)。內(nèi)部類ProxyService實(shí)現(xiàn)了GeneralServer.Service接口。
**/
public class ProxyServer {
// 命令行的格式是:代理服務(wù)器連接的目標(biāo)服務(wù)器的域名、端口以及代理服務(wù)開啟的本地端口
public static final String usage =
"Usage: java book.net.ProxyServer <remotehost> <remoteport> <localport>
";
/**
* 創(chuàng)建一個(gè)GeneralServer對象,并添加代理服務(wù)ProxyService對象到這個(gè)服務(wù)器上。
**/
public static void main(String[] args) {
try {
// 檢驗(yàn)參數(shù)
if ((args.length == 0) || (args.length % 3 != 0)){
throw new IllegalArgumentException("Wrong number of args");
}
// 創(chuàng)建一個(gè)服務(wù)器:GeneralServer對象,用于管理服務(wù),
// 第一個(gè)參數(shù)為null表示服務(wù)器的日志輸出在標(biāo)準(zhǔn)輸出上,第二個(gè)參數(shù)12表示最大連接數(shù)
GeneralServer server = new GeneralServer(null, 12);
// 從命令行中解析參數(shù),可以創(chuàng)建多個(gè)代理服務(wù)
int i = 0;
while(i < args.length) {
// 目標(biāo)服務(wù)器的域名和地址
String remotehost = args[i++];
int remoteport = Integer.parseInt(args[i++]);
// 代理服務(wù)在本地的端口
int localport = Integer.parseInt(args[i++]);
// 創(chuàng)建一個(gè)連接到目標(biāo)服務(wù)器的代理服務(wù)對象,并部署在本地服務(wù)器上的localport端口上。
server.addService(new ProxyService(remotehost, remoteport), localport);
}
}
catch (Exception e) {
System.err.println(e);
System.err.println(usage);
System.exit(1);
}
}
/**
* 實(shí)現(xiàn)代理服務(wù)的功能,實(shí)現(xiàn)了GeneralServer.Service接口的serve方法。
* 首先與目標(biāo)服務(wù)器建立連接,然后將來自客戶端的輸入流輸出到目標(biāo)服務(wù)器端,
* 將來自目標(biāo)服務(wù)器的輸入流輸出到客戶端。
* 輸入輸出流的流向控制是通過2個(gè)線程實(shí)現(xiàn)的。
*/
public static class ProxyService implements GeneralServer.Service {
// 目標(biāo)服務(wù)器的域名和端口
String remotehost;
int remoteport;
/**
* 構(gòu)造方法
*/
public ProxyService(String host, int port) {
this.remotehost = host;
this.remoteport = port;
}
/**
* 當(dāng)客戶端調(diào)用GeneralServer上的代理服務(wù)時(shí),將調(diào)用serve方法
*/
public void serve(InputStream in, OutputStream out) {
// 來自客戶端的輸入流
final InputStream from_client = in;
// 輸出到客戶端的輸出流
final OutputStream to_client = out;
// 與目標(biāo)服務(wù)器的輸入輸出流
final InputStream from_server;
final OutputStream to_server;

// 連接到目標(biāo)服務(wù)器的socket對象
final Socket server;
try {
// 連接目標(biāo)服務(wù)器,初始化from_server,to_server流
server = new Socket(remotehost, remoteport);
from_server = server.getInputStream();
to_server = server.getOutputStream();
} catch (Exception e) {
// 如果連接失敗,則向客戶端發(fā)送失敗的消息
PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
pw.print("Proxy server could not connect to " + remotehost
+ ":" + remoteport + "\n");
pw.flush();
pw.close();
try {
in.close();
} catch (IOException ex) {
}
return;
}
// 創(chuàng)建一個(gè)線程,將來自客戶端的輸入流字節(jié)輸出到目標(biāo)服務(wù)器上
Thread client2server = new Thread() {
public void run() {
byte[] buffer = new byte[2048];
int bytes_read;
try {
// 從來自客戶端的輸入流中讀取數(shù)據(jù),寫到目標(biāo)服務(wù)器上
while ((bytes_read = from_client.read(buffer)) != -1) {
to_server.write(buffer, 0, bytes_read);
to_server.flush();
}
} catch (IOException e) {
} finally {
// 當(dāng)線程結(jié)束時(shí),關(guān)閉與目標(biāo)服務(wù)器的socket連接和2個(gè)輸入輸出流
try {
server.close();
to_client.close();
from_client.close();
} catch (IOException e) {
}
}
}
};

// 創(chuàng)建一個(gè)線程,用于將來自目標(biāo)服務(wù)器的輸入流輸出到客戶端
Thread server2client = new Thread() {
public void run() {
byte[] buffer = new byte[2048];
int bytes_read;
try {
// 讀取來自目標(biāo)服務(wù)器的輸入流from_server,然后輸出到to_client
while ((bytes_read = from_server.read(buffer)) != -1) {
to_client.write(buffer, 0, bytes_read);
to_client.flush();
}
} catch (IOException e) {
} finally {
try {
server.close();
to_client.close();
from_client.close();
} catch (IOException e) {
}
}
}
};

// 啟動這兩個(gè)線程
client2server.start();
server2client.start();

// 當(dāng)這個(gè)兩個(gè)線程運(yùn)行結(jié)束時(shí),本次服務(wù)才結(jié)束
try {
client2server.join();
server2client.join();
} catch (InterruptedException e) {
}
}
}
}
在命令行下輸入"java book.net.ProxyServer www.google.com 80 5555",將啟動代理服務(wù)器,端口為5555.打開瀏覽器,在地址欄中輸入' http://localhost:5555 " 將會打開www.google.com的主頁。


































































































































































在命令行下輸入"java book.net.ProxyServer www.google.com 80 5555",將啟動代理服務(wù)器,端口為5555.打開瀏覽器,在地址欄中輸入' http://localhost:5555 " 將會打開www.google.com的主頁。
-- 學(xué)海無涯