commit 3661cfa8e7f7d3924dc43236ff78db6a46ca1dcf
Author: lisang <1186733841@qq.com>
Date: Thu Jun 27 21:04:09 2024 +0800
first commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..328d131
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,35 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+info.text
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a9bc182
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# 手写RPC框架
+
+> RPC:让你像是在做本地调用一样去调用一个远程服务器上的方法
+
+## RPC相关图示
+
+RPC简单示意图
+
+
+RPC时序图
+
+
+手写RPC简易流程图
+
+
+## RPC需要解决的内容
+
+- 必须要有服务暴露
+- 必须要有远程代理对象
+- 通信
+- 序列化与反序列化
+- IO
\ No newline at end of file
diff --git a/doc/rpc时序图.png b/doc/rpc时序图.png
new file mode 100644
index 0000000..9d39470
Binary files /dev/null and b/doc/rpc时序图.png differ
diff --git a/doc/rpc简易流程.png b/doc/rpc简易流程.png
new file mode 100644
index 0000000..893d737
Binary files /dev/null and b/doc/rpc简易流程.png differ
diff --git a/doc/rpc简示图.png b/doc/rpc简示图.png
new file mode 100644
index 0000000..eae8712
Binary files /dev/null and b/doc/rpc简示图.png differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7efab74
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ 4.0.0
+
+ com.shockkid
+ rpc
+ pom
+ 1.0
+
+ rpc-api
+ rpc-server
+ rpc-client
+
+
+ rpc
+
+ http://www.example.com
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
diff --git a/rpc-api/pom.xml b/rpc-api/pom.xml
new file mode 100644
index 0000000..6c25f69
--- /dev/null
+++ b/rpc-api/pom.xml
@@ -0,0 +1,29 @@
+
+
+
+ 4.0.0
+
+ com.shockkid
+ rpc-api
+ 1.0
+
+ rpc-api
+
+ http://www.example.com
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
diff --git a/rpc-api/src/main/java/com/shockkid/App.java b/rpc-api/src/main/java/com/shockkid/App.java
new file mode 100644
index 0000000..b9c882f
--- /dev/null
+++ b/rpc-api/src/main/java/com/shockkid/App.java
@@ -0,0 +1,13 @@
+package com.shockkid;
+
+/**
+ * Hello world!
+ *
+ */
+public class App
+{
+ public static void main( String[] args )
+ {
+ System.out.println( "Hello World!" );
+ }
+}
diff --git a/rpc-api/src/main/java/com/shockkid/HelloServer.java b/rpc-api/src/main/java/com/shockkid/HelloServer.java
new file mode 100644
index 0000000..4446cd6
--- /dev/null
+++ b/rpc-api/src/main/java/com/shockkid/HelloServer.java
@@ -0,0 +1,9 @@
+package com.shockkid;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 17:02
+ **/
+public interface HelloServer {
+ public String sayHello(String content);
+}
diff --git a/rpc-api/src/main/java/com/shockkid/RpcRequest.java b/rpc-api/src/main/java/com/shockkid/RpcRequest.java
new file mode 100644
index 0000000..3f114fc
--- /dev/null
+++ b/rpc-api/src/main/java/com/shockkid/RpcRequest.java
@@ -0,0 +1,57 @@
+package com.shockkid;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 16:59
+ **/
+public class RpcRequest implements Serializable {
+ private String className;
+ private String methodName;
+ private Object[] parameters;
+ private Class[] types;
+
+ 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;
+ }
+
+ public Class[] getTypes() {
+ return types;
+ }
+
+ public void setTypes(Class[] types) {
+ this.types = types;
+ }
+
+ @Override
+ public String toString() {
+ return "RpcRequest{" +
+ "className='" + className + '\'' +
+ ", methodName='" + methodName + '\'' +
+ ", parameters=" + Arrays.toString(parameters) +
+ ", types=" + Arrays.toString(types) +
+ '}';
+ }
+}
diff --git a/rpc-api/src/test/java/com/shockkid/AppTest.java b/rpc-api/src/test/java/com/shockkid/AppTest.java
new file mode 100644
index 0000000..77525fe
--- /dev/null
+++ b/rpc-api/src/test/java/com/shockkid/AppTest.java
@@ -0,0 +1,20 @@
+package com.shockkid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/rpc-client/pom.xml b/rpc-client/pom.xml
new file mode 100644
index 0000000..a116f69
--- /dev/null
+++ b/rpc-client/pom.xml
@@ -0,0 +1,34 @@
+
+
+
+ 4.0.0
+
+ com.shockkid
+ rpc-client
+ 1.0
+
+ rpc-client
+
+ http://www.example.com
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+ com.shockkid
+ rpc-api
+ 1.0
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
diff --git a/rpc-client/src/main/java/com/shockkid/Client.java b/rpc-client/src/main/java/com/shockkid/Client.java
new file mode 100644
index 0000000..c02b7c1
--- /dev/null
+++ b/rpc-client/src/main/java/com/shockkid/Client.java
@@ -0,0 +1,13 @@
+package com.shockkid;
+
+/**
+ * Hello world!
+ */
+public class Client {
+ public static void main(String[] args) {
+ RpcProxyClient rpcProxyClient = new RpcProxyClient();
+ HelloServer helloServer = rpcProxyClient.clientProxy(HelloServer.class, "localhost", 8081);
+ Object obj = helloServer.sayHello("lisang");
+ System.out.println(obj.toString());
+ }
+}
diff --git a/rpc-client/src/main/java/com/shockkid/RemoteInvocationHandler.java b/rpc-client/src/main/java/com/shockkid/RemoteInvocationHandler.java
new file mode 100644
index 0000000..e908323
--- /dev/null
+++ b/rpc-client/src/main/java/com/shockkid/RemoteInvocationHandler.java
@@ -0,0 +1,30 @@
+package com.shockkid;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 19:51
+ **/
+public class RemoteInvocationHandler implements InvocationHandler {
+ private String host;
+ private int port;
+
+ public RemoteInvocationHandler(String host, int port) {
+ this.host = host;
+ this.port = port;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ RpcRequest request = new RpcRequest();
+ request.setClassName(method.getDeclaringClass().getName());
+ request.setMethodName(method.getName());
+ request.setParameters(args);
+ request.setTypes(method.getParameterTypes());
+ RpcNetTransport rpcNetTransport = new RpcNetTransport(host, port);
+ return rpcNetTransport.send(request);
+ }
+
+}
diff --git a/rpc-client/src/main/java/com/shockkid/RpcNetTransport.java b/rpc-client/src/main/java/com/shockkid/RpcNetTransport.java
new file mode 100644
index 0000000..4646e2f
--- /dev/null
+++ b/rpc-client/src/main/java/com/shockkid/RpcNetTransport.java
@@ -0,0 +1,66 @@
+package com.shockkid;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.Socket;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 19:56
+ **/
+public class RpcNetTransport {
+ private String host;
+ private int port;
+
+ public RpcNetTransport(String host, int port) {
+ this.host = host;
+ this.port = port;
+ }
+
+ private Socket newSocket() throws IOException {
+ System.out.println("开始建立一个连接");
+ Socket socket = null;
+ socket = new Socket(host, port);
+ return socket;
+ }
+
+ public Object send(RpcRequest request) {
+ Socket socket = null;
+ Object result = null;
+ ObjectOutputStream os = null;
+ ObjectInputStream is = null;
+ try {
+ socket = newSocket();
+ os = new ObjectOutputStream(socket.getOutputStream());
+ os.writeObject(request);
+ is = new ObjectInputStream(socket.getInputStream());
+ result = is.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ e.printStackTrace();
+ } finally {
+ if (os != null) {
+ try {
+ os.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return result;
+ }
+}
diff --git a/rpc-client/src/main/java/com/shockkid/RpcProxyClient.java b/rpc-client/src/main/java/com/shockkid/RpcProxyClient.java
new file mode 100644
index 0000000..98c7248
--- /dev/null
+++ b/rpc-client/src/main/java/com/shockkid/RpcProxyClient.java
@@ -0,0 +1,15 @@
+package com.shockkid;
+
+import java.lang.reflect.Proxy;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 20:07
+ **/
+public class RpcProxyClient {
+ public T clientProxy(Class interfacecls, String host, int port) {
+ return (T) Proxy.newProxyInstance(interfacecls.getClassLoader(),
+ new Class[]{interfacecls},
+ new RemoteInvocationHandler(host, port));
+ }
+}
diff --git a/rpc-client/src/test/java/com/shockkid/AppTest.java b/rpc-client/src/test/java/com/shockkid/AppTest.java
new file mode 100644
index 0000000..77525fe
--- /dev/null
+++ b/rpc-client/src/test/java/com/shockkid/AppTest.java
@@ -0,0 +1,20 @@
+package com.shockkid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/rpc-server/pom.xml b/rpc-server/pom.xml
new file mode 100644
index 0000000..50cdcb7
--- /dev/null
+++ b/rpc-server/pom.xml
@@ -0,0 +1,34 @@
+
+
+
+ 4.0.0
+
+ com.shockkid
+ rpc-server
+ 1.0
+
+ rpc-server
+
+ http://www.example.com
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+ com.shockkid
+ rpc-api
+ 1.0
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
diff --git a/rpc-server/src/main/java/com/shockkid/HelloServerImpl.java b/rpc-server/src/main/java/com/shockkid/HelloServerImpl.java
new file mode 100644
index 0000000..049b83f
--- /dev/null
+++ b/rpc-server/src/main/java/com/shockkid/HelloServerImpl.java
@@ -0,0 +1,12 @@
+package com.shockkid;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 17:03
+ **/
+public class HelloServerImpl implements HelloServer {
+ @Override
+ public String sayHello(String content) {
+ return "shockkid " + content + " say hello";
+ }
+}
diff --git a/rpc-server/src/main/java/com/shockkid/ProcessorHandler.java b/rpc-server/src/main/java/com/shockkid/ProcessorHandler.java
new file mode 100644
index 0000000..ade77cc
--- /dev/null
+++ b/rpc-server/src/main/java/com/shockkid/ProcessorHandler.java
@@ -0,0 +1,54 @@
+package com.shockkid;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.Socket;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 17:12
+ **/
+public class ProcessorHandler implements Runnable {
+ Socket socket = null;
+ Object service = null;
+
+ public ProcessorHandler(Socket socket, Object service) {
+ this.socket = socket;
+ this.service = service;
+ }
+
+ @Override
+ public void run() {
+ ObjectInputStream is = null;
+ ObjectOutputStream os = null;
+
+ try {
+ is = new ObjectInputStream(socket.getInputStream());
+ RpcRequest rpcRequest = (RpcRequest) is.readObject();
+ Object result = invoke(rpcRequest);
+
+ os = new ObjectOutputStream(socket.getOutputStream());
+ os.writeObject(result);
+ os.flush();
+ } catch (IOException | ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ Class clazz = Class.forName(request.getClassName());
+ Object[] args = request.getParameters();
+ Method method = clazz.getMethod(request.getMethodName(), request.getTypes());
+ Object obj = method.invoke(service, args);
+ return obj;
+ }
+}
diff --git a/rpc-server/src/main/java/com/shockkid/RpcProxyServer.java b/rpc-server/src/main/java/com/shockkid/RpcProxyServer.java
new file mode 100644
index 0000000..eaff08a
--- /dev/null
+++ b/rpc-server/src/main/java/com/shockkid/RpcProxyServer.java
@@ -0,0 +1,30 @@
+package com.shockkid;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @auther lisang
+ * @date 2024/6/27 17:06
+ **/
+public class RpcProxyServer {
+ private ExecutorService executorService = Executors.newCachedThreadPool();
+
+ public void publisher(Object server,int prot) {
+ ServerSocket serverSocket = null;
+ try {
+ serverSocket = new ServerSocket(prot);
+ while (true) {
+ Socket socket = serverSocket.accept();
+ executorService.execute(new ProcessorHandler(socket, server));
+
+
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/rpc-server/src/main/java/com/shockkid/Server.java b/rpc-server/src/main/java/com/shockkid/Server.java
new file mode 100644
index 0000000..9767bd1
--- /dev/null
+++ b/rpc-server/src/main/java/com/shockkid/Server.java
@@ -0,0 +1,12 @@
+package com.shockkid;
+
+/**
+ * Hello world!
+ */
+public class Server {
+ public static void main(String[] args) {
+ HelloServer helloServer = new HelloServerImpl();
+ RpcProxyServer rpcProxyServer = new RpcProxyServer();
+ rpcProxyServer.publisher(helloServer, 8081);
+ }
+}
diff --git a/rpc-server/src/test/java/com/shockkid/AppTest.java b/rpc-server/src/test/java/com/shockkid/AppTest.java
new file mode 100644
index 0000000..77525fe
--- /dev/null
+++ b/rpc-server/src/test/java/com/shockkid/AppTest.java
@@ -0,0 +1,20 @@
+package com.shockkid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/src/main/java/com/shockkid/App.java b/src/main/java/com/shockkid/App.java
new file mode 100644
index 0000000..b9c882f
--- /dev/null
+++ b/src/main/java/com/shockkid/App.java
@@ -0,0 +1,13 @@
+package com.shockkid;
+
+/**
+ * Hello world!
+ *
+ */
+public class App
+{
+ public static void main( String[] args )
+ {
+ System.out.println( "Hello World!" );
+ }
+}
diff --git a/src/test/java/com/shockkid/AppTest.java b/src/test/java/com/shockkid/AppTest.java
new file mode 100644
index 0000000..77525fe
--- /dev/null
+++ b/src/test/java/com/shockkid/AppTest.java
@@ -0,0 +1,20 @@
+package com.shockkid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}