📄 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 + -