闲话不多说,上来撸代码
-
rpc_client
- 首先,需要拿到服务器端的接口
package com.swh.ami.highVersion.socket.client;
import java.io.Serializable;
public interface ILearnService {
String learn(String name);
}
- 创建接口代理
package com.swh.ami.highVersion.socket.client;
import java.lang.reflect.Proxy;
public class RpcClientProxy {
// 通过代理来创建"实现类"来调用接口中的方法
public <T> T clientProxy(final Class<T> interfaceCls,final String host,final int post){
return (T)Proxy.newProxyInstance(RpcClientProxy.class.getClassLoader(),
new Class[]{interfaceCls},
new RpcClientInvercation(host,post));
}
}
- 实现InvocationHandler接口
package com.swh.ami.highVersion.socket.client;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 实现InvocationHandler接口,实现invoke方法,以便于动态代理生成的代理对象回调
* 因为客户端没有调用方法的实现只有接口,所以代理对象回调时会把需要调用的对象信息(对象名称,方法,参数)
* 通过socket传到服务器端,然后服务器端通过反射的方式执行方法并将结果返回给客户端
*/
public class RpcClientInvercation implements InvocationHandler{
private String host;
private int port;
public RpcClientInvercation(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
RequestDataInfo dataInfo = new RequestDataInfo();
dataInfo.setClassName(method.getDeclaringClass().getName());
dataInfo.setMethodName(method.getName());
dataInfo.setParameters(args);
return new ManagementSocket().handlerSocket(dataInfo, host, port);
}
}
- 创建管理客户端socket
package com.swh.ami.highVersion.socket.client;
import java.io.*;
import java.net.Socket;
/**
* 创建socket连接远程客户端并把调用信息传到服务器
* 同时接口远程服务器返回的信息
*/
public class ManagementSocket {
private Socket newSocket(String host, int port) {
try {
System.out.println("创建一个新的连接");
return new Socket(host, port);
} catch (IOException e) {
throw new RuntimeException("连接异常");
}
}
public Object handlerSocket(RequestDataInfo requestDataInfo, String host, int port) {
Socket socket = null;
OutputStream outputStream = null;
ObjectOutputStream objectOutputStream = null;
InputStream inputStream = null;
ObjectInputStream objectInputStream = null;
try {
socket = newSocket(host, port);
outputStream = socket.getOutputStream();
objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(requestDataInfo);
outputStream.flush();
inputStream = socket.getInputStream();
objectInputStream = new ObjectInputStream(inputStream);
return objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (objectInputStream != null) {
objectInputStream.close();
}
if(inputStream!=null){
inputStream.close();
}
if(objectOutputStream!=null){
objectOutputStream.close();
}
if(outputStream!=null){
outputStream.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
- 传输的对象信息
package com.swh.ami.highVersion.socket.client;
import java.io.Serializable;
public class RequestDataInfo implements Serializable{
private static final long serialVersionUID = 3121764803401713947L;
private String className;
private String methodName;
private Object[] parameters;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getParameters() {
return parameters;
}
public void setParameters(Object[] parameters) {
this.parameters = parameters;
}
}
- 客户端的调用
package com.swh.ami.highVersion.socket.client;
import java.io.*;
public class SocketClientA {
public static void main(String[] args) throws IOException {
RpcClientProxy rpcClientProxy = new RpcClientProxy();
// 此处使用动态代理的目的是,易于扩展,当新增其他服务接口的时候只需要修改接口的进来就可以了
ILearnService iLearnService = rpcClientProxy.clientProxy(ILearnService.class, "127.0.0.1", 10222);
String learn = iLearnService.learn("111");
System.out.println(learn);
}
}
2.rpc_server
- 服务器提供的服务方法
package com.swh.ami.highVersion.socket.client;
public interface ILearnService {
String learn(String name);
}
package com.swh.ami.highVersion.socket.client;
public class LearnServiceImpl implements ILearnService {
@Override
public String learn(String name) {
return "我要学习," + name;
}
}
- socket服务端接收,并处理
package com.swh.ami.highVersion.socket.client;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* socket 编程基础多线程版
*
* ① 创建ServerSocket对象,绑定监听端口
② 通过accept()方法监听客户端请求
③ 连接建立后,通过输入流读取客户端发送的请求信息
④ 通过输出流向客户端发送乡音信息
⑤ 关闭相关资源
*/
public class SocketServiceThread {
private Object serverName;
private int port;
public SocketServiceThread(Object serverName, int port) {
this.serverName = serverName;
this.port = port;
}
public void publishServer() throws IOException {
/**
* ① 服务器端创建ServerSocket,循环调用accept()等待客户端连接
② 客户端创建一个socket并请求和服务器端连接
③ 服务器端接受苦读段请求,创建socket与该客户建立专线连接
④ 建立连接的两个socket在一个单独的线程上对话
⑤ 服务器端继续等待新的连接
*/
// 创建serverSocket对象绑定监听端口
ServerSocket serverSocket = new ServerSocket(port);
Socket accept = null;
int count = 0;
while (true){
accept = serverSocket.accept();
ServiceThread serviceThread = new ServiceThread(accept,serverName);
new Thread(serviceThread).start();
count++;
System.out.println(count);
}
}
}
package com.swh.ami.highVersion.socket.client;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ServiceThread implements Runnable{
Socket socket = null;
private Object serverName;
public ServiceThread(Socket socket,Object serverName) {
this.socket = socket;
this.serverName = serverName;
}
@Override
public void run() {
// 创建serverSocket对象绑定监听端口
try {
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
RequestDataInfo requestDataInfo = (RequestDataInfo) objectInputStream.readObject();
Class[] classes = new Class[requestDataInfo.getParameters().length];
Object[] parameters = requestDataInfo.getParameters();
for (int i = 0 ;i<parameters.length;i++){
classes[i]=parameters[i].getClass();
}
Object invoke = serverName.getClass().getMethod(requestDataInfo.getMethodName(), classes).invoke(serverName, parameters);
System.out.println(invoke);
/* Object invoke = Class.forName(requestDataInfo.getClassName())
.getMethod(requestDataInfo.getMethodName(), classes)
.invoke(requestDataInfo.getMethodName(), parameters);*/
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(invoke);
objectOutputStream.flush();
objectInputStream.close();
outputStream.close();
objectInputStream.close();
inputStream.close();
socket.close();
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
- 服务器也需要一个传输对象
package com.swh.ami.highVersion.socket.client;
import java.io.Serializable;
public class RequestDataInfo implements Serializable{
private static final long serialVersionUID = 3121764803401713947L;
private String className;
private String methodName;
private Object[] parameters;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getParameters() {
return parameters;
}
public void setParameters(Object[] parameters) {
this.parameters = parameters;
}
}
- 服务端发布服务
package com.swh.ami.highVersion.socket.client;
import java.io.IOException;
public class DemoServer {
public static void main(String[] args) throws IOException {
ILearnService learnService = new LearnServiceImpl();
SocketServiceThread serviceThread = new SocketServiceThread(learnService, 10222);
serviceThread.publishServer();
}
}