?? simpleproxyserver.java
字號:
import java.io.*;
import java.net.*;
/**
* 這個(gè)類實(shí)現(xiàn)了一個(gè)簡單的單線程的代理服務(wù)器
*/
public class SimpleProxyServer {
/** 主函數(shù)解析參數(shù)并把參數(shù)傳遞給runServer */
public static void main(String[] args) throws IOException {
try {
// 檢查參數(shù)的個(gè)數(shù)
if (args.length != 3)
throw new IllegalArgumentException("Wrong number of args.");
// 獲得命令行參數(shù): 我們要代理的主機(jī)和端口
String host = args[0];
int remoteport = Integer.parseInt(args[1]);
int localport = Integer.parseInt(args[2]);
// 顯示開始信息
System.out.println("Starting proxy for " + host + ":" +
remoteport + " on port " + localport);
// 開始運(yùn)行這個(gè)服務(wù)器
runServer(host, remoteport, localport); // 永不返回
}
catch (Exception e) {
System.err.println(e);
System.err.println("Usage: java SimpleProxyServer " +
"<host> <remoteport> <localport>");
}
}
/**
* 這個(gè)方法運(yùn)行一個(gè)單線程的代理服務(wù)器,它在指定的本地端口上
* 代理一個(gè)主機(jī)上的遠(yuǎn)程端口。它用不返回。
*/
public static void runServer(String host, int remoteport, int localport)
throws IOException {
// 創(chuàng)建一個(gè)ServerSocket來監(jiān)聽連接
ServerSocket ss = new ServerSocket(localport);
// 為客戶端到服務(wù)器和服務(wù)器到客戶端創(chuàng)建緩沖區(qū)
// 我們指定緩沖區(qū)為final,使它能夠在下面的匿名類中能夠被使用
// 注意在每個(gè)方向上交換量上的假定
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
// 這是一個(gè)用不返回的服務(wù)器,故進(jìn)入一個(gè)無限循環(huán)
while(true) {
// 保持與客戶端和與服務(wù)器連接的socket的變量
Socket client = null, server = null;
try {
// 等待一個(gè)本地端口的連接
client = ss.accept();
// 獲取客戶流,把他們定義成final使得他們在下面的匿名
// 類中能夠被使用
final InputStream from_client = client.getInputStream();
final OutputStream to_client = client.getOutputStream();
// 建立一個(gè)與真實(shí)服務(wù)器的連接
// 如果我們不能連上服務(wù)器,發(fā)送一個(gè)錯(cuò)誤給客戶端
// 取消連接,等待下次連接
try { server = new Socket(host, remoteport); }
catch (IOException e) {
PrintWriter out = new PrintWriter(to_client);
out.print("Proxy server cannot connect to " + host + ":"+
remoteport + ":\n" + e + "\n");
out.flush();
client.close();
continue;
}
// 獲得服務(wù)器的流
final InputStream from_server = server.getInputStream();
final OutputStream to_server = server.getOutputStream();
// 創(chuàng)建一個(gè)線程讀取客戶端的請求,把請求傳遞給服務(wù)器,我們不得不
// 使用一個(gè)獨(dú)立的線程,因?yàn)檎埱蠛晚憫?yīng)是異步的
Thread t = new Thread() {
public void run() {
int bytes_read;
try {
while((bytes_read=from_client.read(request))!=-1) {
to_server.write(request, 0, bytes_read);
to_server.flush();
}
}
catch (IOException e) {}
// 客戶端關(guān)閉了同我們的連接,那么也就關(guān)閉了我們與服務(wù)器的
// 連接。這將造成主線程中服務(wù)器與客戶端之間的循環(huán)退出
try {to_server.close();} catch (IOException e) {}
}
};
// 開始客戶端到服務(wù)器請求線程的運(yùn)行
t.start();
// 同時(shí),在主線程中,讀取服務(wù)器的響應(yīng),并把它們傳遞給客戶端。這將
// 與上面提到的客戶端到服務(wù)器的請求線程并行執(zhí)行
int bytes_read;
try {
while((bytes_read = from_server.read(reply)) != -1) {
to_client.write(reply, 0, bytes_read);
to_client.flush();
}
}
catch(IOException e) {}
// 服務(wù)器關(guān)閉同我們的連接,那么我們關(guān)閉與客戶端的連接
// 這將使另外一個(gè)線程退出
to_client.close();
}
catch (IOException e) { System.err.println(e); }
finally { // 不管發(fā)生什么關(guān)閉線程
try {
if (server != null) server.close();
if (client != null) client.close();
}
catch(IOException e) {}
}
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -