⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxyserver.java

📁 JAVA2(J2ME)实用编程的150个范例
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
import java.io.*;
import java.net.*;
import java.util.*;
// main() 方法启动代理服务器。具体由内嵌的Proxy类实现
public class ProxyServer {
public static void main(String[] args) {
try {
// 检查args参数数
if ((args.length == 0) || (args.length % 3 != 0))
throw new IllegalArgumentException("Wrong number of args");
// 创建Server对象
Server s = new Server(null, 12);
// 对每个循环创建一个 Proxy并把它添加到 server.
int i = 0;
while(i < args.length) {
String host = args[i++];
int remoteport = Integer.parseInt(args[i++]);
int localport = Integer.parseInt(args[i++]);
s.addService(new Proxy(host, remoteport), localport);
}
}
catch (Exception e) {  // 若出错打印错误信息
System.err.println(e);
System.err.println("Usage: java ProxyServer " +"<host> <remoteport> <localport> ...");
System.exit(1);
}
}

// 接下来是一个实现了代理服务的类。当有客户端连接时调用serve()方法
// 此时必须首先建立一个连接并在客户和服务器端之间传输数据
// 这个类实现了两个相似线程作为匿名类, 一个线程从客户端拷贝数据到服务器端
// 另一个从服务器端到客户端拷贝数据。线程调用serve()方法创建和启动这些线程,然后等待
// 它们退出
public static class Proxy implements Server.Service {
String host;
int port;

// 记住代理的主机和端口
public Proxy(String host, int port) {
this.host = host;
this.port = port;
}
// 当有一个客户端连接时服务器端调用这个方法
public void serve(InputStream in, OutputStream out) {
final InputStream from_client = in;
final OutputStream to_client = out;
final InputStream from_server;
final OutputStream to_server;
// 建立到某一个服务器端端口的连接并返回出错信息
final Socket server;
try {
server = new Socket(host, port);
from_server = server.getInputStream();
to_server = server.getOutputStream();
}
catch (Exception e) {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
pw.print("Proxy server could not connect to " + host +":" + port + "\n");
pw.flush();
pw.close();
try { in.close(); } catch (IOException ex) {}
return;
}
// 建立一个数组保存两个线程。
final Thread[] threads = new Thread[2];
// 建立一个线程从客户端到服务器端拷贝数据
Thread c2s = new Thread() {
public void run() {
byte[] buffer = new byte[2048];
int bytes_read;
try {
while((bytes_read=from_client.read(buffer))!=-1) {
to_server.write(buffer, 0, bytes_read);
to_server.flush();
}
}
catch (IOException e) {}
finally {
// 当线程任务结束时
try {
server.close();
to_client.close();
from_client.close();
}
catch (IOException e) {}
}
}
};
// 建立一个线程从服务器端到客户端拷贝数据.
// 这些线程和上面那个工作机理一样
Thread s2c = new Thread() {
public void run() {
byte[] buffer = new byte[2048];
int bytes_read;
try {
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) {}
}
}
};
// 把线程保存在 threads[]数组中以便匿名类之间可以相互引用
threads[0] = c2s; threads[1] = s2c;
// 启动线程
c2s.start(); s2c.start();
// 等待他们退出
try { c2s.join(); s2c.join(); } catch (InterruptedException e) {}
}
}
}

// 下面的多线程server类框架,实现对端口的监听和数据传输的实时控制
class Server {   // 定义Server 类
// server的状态量
Map services;
Set connections;
int maxConnections;
ThreadGroup threadGroup;
PrintWriter logStream;
public Server(OutputStream logStream, int maxConnections) { // 构造函数
setLogStream(logStream);
log("Starting server"); // 记录日志信息
threadGroup = new ThreadGroup(Server.class.getName());
this.maxConnections = maxConnections;
services = new HashMap();
connections = new HashSet(maxConnections);
}

// 一个公共的方法 来设置当前登陆流,传递null来关闭登陆
public synchronized void setLogStream(OutputStream out) {
if (out != null) logStream = new PrintWriter(out);
else logStream = null;
}

// 记录日志函数
protected synchronized void log(String s) {
if (logStream != null) {
logStream.println("[" + new Date() + "] " + s);
logStream.flush();
}
}

protected void log(Object o) { log(o.toString()); }   // 把某个对象object写入log

// 使server在特定端口开特定服务
public synchronized void addService(Service service, int port)  throws IOException
{
Integer key = new Integer(port);
// 检查在某个端口是否已经有其它service
if (services.get(key) != null)
throw new IllegalArgumentException("端口 " + port +" 已经被使用.");
// 创建监听类来监听端口的连接情况
Listener listener = new Listener(threadGroup, port, service);
// 保存在哈希表中
services.put(key, listener);
// 写log
log("启动服务: " + service.getClass().getName() + " 端口为: " + port);
// 开始监听
listener.start();
}

// 使server停止某个端口上的服务
public synchronized void removeService(int port) {
Integer key = new Integer(port);  // 哈希表关键字
// 在哈希表中查找对某个端口的监听对象
final Listener listener = (Listener) services.get(key);
if (listener == null) return;
// 使得监听器停止
listener.pleaseStop();
// 从哈希表中删除
services.remove(key);
// 写log.
log("停止服务: " + listener.service.getClass().getName() + " 端口: " + port);
}
}

// 下面是一个监听器,它监听来自某一个特定端口的连接。
// 当它获得一个连接请求时,它调用服务器的addConnection()方法来接受或拒绝连接
public class Listener extends Thread {
ServerSocket listen_socket;    // 监听连接的套接字
int port;                      // 端口
Service service;               // 在端口上实现的服务
volatile boolean stop = false; // 标志是否被请求停止
// 创建一个服务器套接字来监听某个特定端口的连接
public Listener(ThreadGroup group, int port, Service service) throws IOException
{
super(group, "Listener:" + port);
listen_socket = new ServerSocket(port);
// 给出一个非零超时信号使得accept()被中断
listen_socket.setSoTimeout(600000);
this.port = port;
this.service = service;
}

// 停止接收连接
public void pleaseStop() {
this.stop = true;              // 设置停止标志位
this.interrupt();              // 停止阻断accept()
try { listen_socket.close(); } // 停止监听.
catch(IOException e) {}
}


// 等待连接请求,接受,接着把socket传给sever的addConnection方法
public void run() {
while(!stop) {      // 循环直到要求停止
try {
Socket client = listen_socket.accept();
addConnection(client, service);
}
catch (InterruptedIOException e) {}
catch (IOException e) {log(e);}
}
}

// 当接受客户端连接以后这个方法将会被监听器调用
// 或者创建一个连接类,或者把这个连接加入到现有的连接列表中,抑或关闭连接
protected synchronized void addConnection(Socket s, Service service) {
// 如果到达连接上限
if (connections.size() >= maxConnections) {
try {
// 则告诉客户端正在被拒绝.
PrintWriter out = new PrintWriter(s.getOutputStream());
out.print("连接被拒绝; " +"服务器忙,请稍后再试.\n");
out.flush();
//关闭连接
s.close();
// 写log
log("连接被拒绝:" +s.getInetAddress().getHostAddress() +
":" + s.getPort() + ": 达到最大连接数.");
} catch (IOException e) {log(e);}
}
else {  // 如果连接数未到上限
// 创建一个线程处理连接
Connection c = new Connection(s, service);
// 并把它添加到当前连接列表中
connections.add(c);
// 把这个新的连接写入log
log("Connected to " + s.getInetAddress().getHostAddress() +":" + s.getPort() + " on port " +
s.getLocalPort() +" for service " + service.getClass().getName());
// 开始连接线程提供服务

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -