?? proxyserver.java
字號:
c.start();
}
}
// 在連接線程退出前調用這個函數,它把某個特定線程從線程列表中刪除
protected synchronized void endConnection(Connection c) {
connections.remove(c);
log("連接到: " + c.client.getInetAddress().getHostAddress() +":" + c.client.getPort() + " 關閉.");
}
// 改變現有的連接上限
public synchronized void setMaxConnections(int max) {
maxConnections = max;
}
// 顯示server信息
public synchronized void displayStatus(PrintWriter out) {
// 顯示所有服務的列表
Iterator keys = services.keySet().iterator();
while(keys.hasNext()) {
Integer port = (Integer) keys.next();
Listener listener = (Listener) services.get(port);
out.print("SERVICE " + listener.service.getClass().getName()+ " ON PORT " + port +
"\n");
}
// 顯示現有連接上限
out.print("MAX CONNECTIONS: " + maxConnections + "\n");
// 顯示現有連接列表
Iterator conns = connections.iterator();
while(conns.hasNext()) {
Connection c = (Connection)conns.next();
out.print("連接: " +c.client.getInetAddress().getHostAddress() +
":" + c.client.getPort() + " 端口:" +c.client.getLocalPort() +
c.service.getClass().getName() + "\n");
}
}
}
public class Connection extends Thread { // 多線程連接類
Socket client; //與客戶端對話的套接字
Service service; //提供給客戶端的service
public Connection(Socket client, Service service) {// 構造函數
super("Server.Connection:" +client.getInetAddress().getHostAddress() +
":" + client.getPort());
this.client = client;
this.service = service;
}
// 把客戶端的輸入輸出流傳給某個Service對象的 serve()方法
public void run() {
try {
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
service.serve(in, out);
}
catch (IOException e) {log(e);}
finally { endConnection(this); }
}
}
public interface Service {
public void serve(InputStream in, OutputStream out) throws IOException;
}
// 一個簡單的service,它向客戶端顯示當前sever上的時間并負責關閉客戶端連接
public static class Time implements Service {
public void serve(InputStream i, OutputStream o) throws IOException {
PrintWriter out = new PrintWriter(o);
out.print(new Date() + "\n");
out.close();
i.close();
}
}
// 這是另外一個簡單的service. 它從客戶端讀入輸入行,然后發送回去然后反轉
// 同時顯示歡迎信息,當用戶鍵入'.'作為一行的結尾時關閉連接
public static class Reverse implements Service {
public void serve(InputStream i, OutputStream o) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(i));
PrintWriter out =new PrintWriter(new BufferedWriter(new OutputStreamWriter(o)));
out.print("Welcome to the line reversal server.\n");
out.print("Enter lines. End with a '.' on a line by itself.\n");
for(;;) {
out.print("> ");
out.flush();
String line = in.readLine();
if ((line == null) || line.equals(".")) break;
for(int j = line.length()-1; j >= 0; j--)
out.print(line.charAt(j));
out.print("\n");
}
out.close();
in.close();
}
}
// 這個服務是一個HTTP映射, 它返回客戶的 HTTP請求
public static class HTTPMirror implements Service {
public void serve(InputStream i, OutputStream o) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(i));
PrintWriter out = new PrintWriter(o);
out.print("HTTP/1.0 200 \n");
out.print("Content-Type: text/plain\n\n");
String line;
while((line = in.readLine()) != null) {
if (line.length() == 0) break;
out.print(line + "\n");
}
out.close();
in.close();
}
}
public static class UniqueID implements Service {
public int id=0;
public synchronized int nextId() { return id++; }
public void serve(InputStream i, OutputStream o) throws IOException {
PrintWriter out = new PrintWriter(o);
out.print("You are client #: " + nextId() + "\n");
out.close();
i.close();
}
}
// 解析一個基于命令的協議,通過這個協議可以提供具有密碼保護的對服務的實時控制
public static class Control implements Service {
Server server;
String password;
boolean connected = false; // 是否有某個客戶連接
// 創建一個新的控制服務,它將控制某個特定的Server對象, 并需要
// 密碼驗證以獲取相關權限,注意這個Service的構造器包含參數
public Control(Server server, String password) {
this.server = server;
this.password = password;
}
// 這是負責提供服務的方法,它讀入客戶端的命令行,并解析為相關命令和參數
public void serve(InputStream i, OutputStream o) throws IOException {
// 創建流
BufferedReader in = new BufferedReader(new InputStreamReader(i));
PrintWriter out = new PrintWriter(o);
String line;
// 用戶是否已提供密碼?
boolean authorized = false;
// 如果已經有一個客戶端連接,則向客戶端發送一個消息并關閉連接
// 在此使用一個synchronized區段來防止資源競爭
synchronized (this) {
if (connected) {
out.print("ONLY ONE CONTROL CONNECTION ALLOWED.\n");
out.close();
return;
}
else
connected = true;
}
// 這是主循環:讀取一條命令,然后解析處理
for (; ; ) { // 無限循環
out.print("> ");
out.flush();
line = in.readLine(); // 獲取用戶輸入
if (line == null)
break; // 如果 EOF則退出
try {
// 使用StringTokenizer來解析用戶命令
StringTokenizer t = new StringTokenizer(line);
if (!t.hasMoreTokens())
continue; //如果輸入為空
// 獲得輸入的第一個詞并轉換成小寫
String command = t.nextToken().toLowerCase();
// 與可能的各種命令比較并執行相應操作
if (command.equals("password")) {
String p = t.nextToken(); // 獲取下一個
if (p.equals(this.password)) { // 密碼是否正確
out.print("OK\n");
authorized = true; // 授予權限
}
else
out.print("INVALID PASSWORD\n"); // 否則失敗
}
else if (command.equals("add")) {
// 檢查是否提供了密碼
if (!authorized)
out.print("PASSWORD REQUIRED\n");
else {
// 獲得服務的名稱并嘗試動態載入、實例化并處理異常
String serviceName = t.nextToken();
Class serviceClass = Class.forName(serviceName);
Service service;
try {
service = (Service) serviceClass.newInstance();
}
catch (NoSuchMethodError e) {
throw new IllegalArgumentException(
"Service must have a " +
"no-argument constructor");
}
int port = Integer.parseInt(t.nextToken());
// 如果沒有產生異常,則添加服務
server.addService(service, port);
out.print("SERVICE ADDED\n"); // 確認
}
}
else if (command.equals("remove")) {
if (!authorized)
out.print("PASSWORD REQUIRED\n");
else {
int port = Integer.parseInt(t.nextToken());
server.removeService(port); // 取消服務
out.print("SERVICE REMOVED\n");
}
}
else if (command.equals("max")) { // 設置連接上限
if (!authorized)
out.print("PASSWORD REQUIRED\n");
else {
int max = Integer.parseInt(t.nextToken());
server.setMaxConnections(max);
out.print("MAX CONNECTIONS CHANGED\n"); //確認
}
}
else if (command.equals("status")) { // 顯示狀態
if (!authorized)
out.print("PASSWORD REQUIRED\n");
else
server.displayStatus(out);
}
else if (command.equals("help")) { // 幫助命令
// 顯示命令語法,不需要密碼
out.print("COMMANDS:\n" + "\tpassword <password>\n" +
"\tadd <service> <port>\n" + "\tremove <port>\n" +
"\tmax <max-connections>\n" + "\tstatus\n" + "\thelp\n" +
"\tquit\n");
}
else if (command.equals("quit"))
break;
else
out.print("UNRECOGNIZED COMMAND\n"); // 出現錯誤
}
catch (Exception e) {
out.print("ERROR WHILE PARSING OR EXECUTING COMMAND:\n" + e + "\n");
}
}
// 關閉流并把連接標志位設為false使得其它客戶端連接
connected = false;
out.close();
in.close();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -