package com.pku.rpc_client;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import javax.swing.text.html.HTMLDocument.Iterator;
import com.pku.rpc_exception.NoSuchServiceException;
import com.pku.rpc_register.ServiceDiscovery;
public class AsyncProxy<T> {
private Class<T> interfaceClass;
private ServiceDiscovery serviceDiscovery;
private Object results;
public AsyncProxy(Class<T> interfaceClass, ServiceDiscovery serviceDiscovery) {
this.interfaceClass = interfaceClass;
this.serviceDiscovery = serviceDiscovery;
}
public void call(String methodname, Object... args) {
// 获取可用服务器的地址
String className = interfaceClass.getName();
String interfacename = className.substring(className.lastIndexOf(".") + 1, className.length());
String serverAddress = serviceDiscovery.discoverService(interfacename);
final String host;
final int port;
if (serverAddress != null) {
String[] address = serverAddress.split(":");
host = address[0];
port = Integer.parseInt(address[1]);
} else {
throw new NoSuchServiceException("没有提供相应的服务!");
}
Class<?>[] parameterTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; ++i) {
parameterTypes[i] = args[i].getClass();
}
try {
Method method = interfaceClass.getDeclaredMethod(methodname, parameterTypes);
Socket socket = new Socket(host, port);
try {
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
try {
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
try {
// input流不能关闭,直到任务完成才能关闭
final ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
// 通过FutureTask类通过新建一个线程等待结果,实现异步调用,并将结果保存在this对象中,以便随时获取
Object result = input.readObject();
if (result instanceof Throwable) {
this.results = (Throwable)result;
}else{
this.results = result;
}
} catch (Exception e) {
e.printStackTrace();
}
} finally {
output.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public Object getResult() throws InterruptedException, ExecutionException {
return this.results;
}
}