最近遇到一个java socket问题,具体业务场景不做描述,只谈谈具体的技术需求,如下所述:
1.client端从server端下载java class文件.
2.完成后动态加载该类,并调用该类的某个方法。
关键点:
1.利用java socket传递java class文件。
2.如何将某path下的java class文件加载到JVM。
测试实现:
需求很明确,没有特别的地方,如下是我写的测试代码。
DataClient: 传递类名等信息到server,从服务端下载指定的java类文件。
DataServer: 根据client端参数传递指定的类文件到client端。
MyClassLoader:以byte格式读取class文件,并加载到JVM。
SocketTool: java socket工具类。
TestClass: 被传递的java class。
package org.socket; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.ServerSocket; import java.net.Socket; /** * Supply for class file download * * @author chares * @date 2013-5-9 * */ public class DataServer { int port = 8821; void start() { Socket socket = null; try { ServerSocket serverSocket = new ServerSocket(port); while (true) { // 选择进行传输的文件 String filePath = "c:\\TestClass.class"; File fi = new File(filePath); System.out.println("~~~~ [server] 文件长度:" + (int) fi.length()); socket = serverSocket.accept(); System.out.println("~~~~ [server] : 建立socket链接"); DataInputStream dis = new DataInputStream( new BufferedInputStream(socket.getInputStream())); dis.readByte(); DataInputStream fis = new DataInputStream( new BufferedInputStream(new FileInputStream(filePath))); DataOutputStream ps = new DataOutputStream(socket.getOutputStream()); // 将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java // 4th里有现成的代码 ps.writeUTF(fi.getName()); ps.flush(); ps.writeLong((long) fi.length()); ps.flush(); int bufferSize = 8192; byte[] buf = new byte[bufferSize]; while (true) { int read = 0; if (fis != null) { read = fis.read(buf); // 从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b // 中。以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾 (end of file) // 或抛出异常之前,此方法将一直阻塞。 } if (read == -1) { break; } ps.write(buf, 0, read); } ps.flush(); // 注意关闭socket链接哦,不然客户端会等待server的数据过来, // 直到socket超时,导致数据不完整。 fis.close(); socket.close(); System.out.println("~~~~ [server] 文件传输完成"); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String arg[]) { new DataServer().start(); } }
package org.socket; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; /** * Get class file from DataServer. * * @author chares * @date 2013-5-9 * */ public class DataClient { private SocketTool cs = null; private String ip = "localhost";// 设置成服务器IP private int port = 8821; private String sendMessage = "Windows"; public DataClient() { try { if (createConnection()) { sendMessage(); getMessage(); } } catch (Exception ex) { ex.printStackTrace(); } } private boolean createConnection() { cs = new SocketTool(ip, port); try { cs.crtConnection(); System.out.print("~~~~ [client] : 连接服务器成功!" + "\n"); return true; } catch (Exception e) { System.out.print("~~~~ [client] : 连接服务器失败!" + "\n"); return false; } } private void sendMessage() { if (cs == null) return; try { cs.sendMessage(sendMessage); } catch (Exception e) { System.out.print("~~~~ [client] : 发送消息失败!" + "\n"); } } private void getMessage() { if (cs == null) return; DataInputStream inputStream = null; try { inputStream = cs.getMessageStream(); } catch (Exception e) { System.out.print("~~~~ [client] : 接收消息缓存错误\n"); return; } try { // 本地保存路径,文件名会自动从服务器端继承而来 String savePath = "d:\\test_java\\"; int bufferSize = 8192; byte[] buf = new byte[bufferSize]; int passedlen = 0; long len = 0; savePath += inputStream.readUTF(); DataOutputStream fileOut = new DataOutputStream( new BufferedOutputStream(new BufferedOutputStream( new FileOutputStream(savePath)))); len = inputStream.readLong(); System.out.println("~~~~ [client] : 文件的长度为:" + len + "\n"); System.out.println("~~~~ [client] : 开始接收文件!" + "\n"); while (true) { int read = 0; if (inputStream != null) { read = inputStream.read(buf); } passedlen += read; if (read == -1) { break; } // 下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比 System.out.println("~~~~ [client] : 文件接收了" + (passedlen * 100 / len) + "%\n"); fileOut.write(buf, 0, read); } System.out.println("~~~~ [client] : 接收完成,文件存为" + savePath + "\n"); fileOut.close(); } catch (Exception e) { System.out.println("~~~~ [client] : 接收消息错误" + "\n"); e.printStackTrace(); } } public static void main(String arg[]) { new DataClient();//download class File new MyClassLoader().load("org.socket.TestClass","getName","");// load class } }
package org.socket; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; public class SocketTool { private String ip; private int port; private Socket socket = null; DataOutputStream out = null; DataInputStream getMessageStream = null; public SocketTool(String ip, int port) { this.ip = ip; this.port = port; } /** * 创建socket连接 * @throws Exception */ public void crtConnection() throws Exception { try { socket = new Socket(ip, port); } catch (Exception e) { e.printStackTrace(); if (socket != null) socket.close(); throw e; } finally { } } public void sendMessage(String sendMessage) throws Exception { try { out = new DataOutputStream(socket.getOutputStream()); if (sendMessage.equals("Windows")) { out.writeByte(0x1); out.flush(); return; } if (sendMessage.equals("Unix")) { out.writeByte(0x2); out.flush(); return; } if (sendMessage.equals("Linux")) { out.writeByte(0x3); out.flush(); } else { out.writeUTF(sendMessage); out.flush(); } } catch (Exception e) { e.printStackTrace(); if (out != null) out.close(); throw e; } finally { } } public DataInputStream getMessageStream() throws Exception { try { getMessageStream = new DataInputStream(new BufferedInputStream( socket.getInputStream())); return getMessageStream; } catch (Exception e) { e.printStackTrace(); if (getMessageStream != null) getMessageStream.close(); throw e; } finally { } } public void shutDownConnection() { try { if (out != null) out.close(); if (getMessageStream != null) getMessageStream.close(); if (socket != null) socket.close(); } catch (Exception e) { } } }
package org.socket; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; /** * Custom class loader * * @author chares * @date 2013-5-9 * */ public class MyClassLoader extends ClassLoader { public static final String DIR_PATH = "file:d:\\test_java\\"; public static final String DONET_CLASS = ".class"; /** * Load java class and invoke the method * * @param methodName * @param params String:param1|String:param2 * */ public void load(String fullClassName, String methodName, String params) { try { Class clazz = loadClass(fullClassName, this.getClassPathAbsolute(fullClassName)); System.out.println("~~~~ clazz's classloader : "+ clazz.getClassLoader()); // Class clazz = Class.forName(CLASS_NAME); Method[] methods = clazz.getDeclaredMethods(); if (methods != null && methods.length > 0) { for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(methodName)) { Object object = clazz.newInstance(); System.out.println("~~~~ object : "+ object); Object rtnObj = methods[i].invoke(object, new Object[]{}); System.out.println("~~~~ rtnObj : "+ rtnObj); } } } } catch (Exception e) { e.printStackTrace(); } } /** * Get java.lang.Class from a XX.class file * @param name * @param classUrl * @return * @throws ClassNotFoundException */ public Class loadClass(String name, String classUrl) throws ClassNotFoundException { if (!"org.socket.TestClass".equals(name)) return super.loadClass(name); try { /* * String url = "file:C:/data/projects/tutorials/web/WEB-INF/" + * "classes/reflection/MyObject.class"; */ URL myUrl = new URL(classUrl); URLConnection connection = myUrl.openConnection(); InputStream input = connection.getInputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int data = input.read(); while (data != -1) { buffer.write(data); data = input.read(); } input.close(); byte[] classData = buffer.toByteArray(); return defineClass(name, classData, 0, classData.length); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * Get absolute path from the java full class name(org.socket.TestClass) * @param fullClassName * @return */ private String getClassPathAbsolute(String fullClassName){ String[] parts = fullClassName.split("\\."); if(parts != null && fullClassName.length() > 0){ return DIR_PATH + parts[parts.length - 1] + DONET_CLASS; } return ""; } public static void main(String[] args) { //ClassLoader parentCl = MyClassLoader.class.getClassLoader(); //System.out.println("~~~~ parentCl classloader : "+ parentCl); new MyClassLoader().load("org.socket.TestClass","getName","");// load class } }
package org.socket; /** * @author chares * */ public class TestClass { public String name = "init"; public String getName() { return name; } public void setName(String name) { this.name = name; } }
相关推荐
在Java中,`java.net.Socket`类和`java.net.ServerSocket`类用于创建客户端和服务器端的Socket连接。在这个聊天应用中,服务器端使用`ServerSocket`监听特定端口,等待客户端的连接请求;客户端则使用`Socket`与...
本教程将详细解释如何在Android中实现Java和C的Socket通信,特别是在涉及文件描述符传递的场景下。 1. **Java Socket基础** Java中的`java.net.Socket`类提供了网络通信的能力,它允许我们在两个应用程序之间建立...
Java中的基于Socket的文件传输服务是一种通过网络进行文件交互的方式,它利用了TCP/IP协议栈中的Socket接口。在Java中,Socket是网络通信的基础,它提供了应用程序与网络之间的连接通道,使得两个网络节点(通常是...
本项目实现了一个基于Socket的文件传输方案,其中Java作为服务端,C++作为客户端,使得Windows环境下的文件能够在两个程序之间安全、高效地传递。以下是对这个程序设计和实现的关键知识点的详细说明: 1. **Java ...
1. **创建Socket对象**:在客户端,使用`java.net.Socket`类创建一个Socket实例,指定服务器的IP地址和端口号。 2. **建立连接**:调用`Socket`对象的`connect()`方法,向服务器发起连接请求。 3. **数据传输**:...
在Java中,Socket通信基于TCP/IP协议栈,提供了稳定的数据传输能力,能够支持多种数据类型如文件、实体类和字符串的发送。本节将深入探讨Socket通信的工作原理、如何发送不同类型的 data以及其在实际项目中的应用。 ...
首先,Java提供了Socket编程接口来实现网络通信,包括文件传输。在服务器端,我们需要创建一个ServerSocket监听特定的端口,等待客户端连接。以下是一个简单的服务器端代码片段: ```java import java.io.*; import...
在这个场景中,我们将深入探讨如何使用Java的Socket API实现文件的上传和下载功能。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它为上层应用提供了稳定的数据...
首先,Java中的Socket类代表了网络上的一个端点,而ServerSocket类用于监听客户端的连接请求。在双机通信中,通常一台机器作为服务器(Server),另一台作为客户端(Client)。服务器需要先启动并监听特定的端口,...
导入这个JAR文件到Java项目中,开发者就可以在Java代码中方便地使用ZeroMQ的功能,例如创建socket、设置socket选项、发送和接收消息等。 在描述中提到的"已经编译了zeromq及jzmq"意味着,这些文件都是预先编译好的...
本文将深入探讨如何使用JavaScript调用Java类的方法,以实现客户端和服务器端的有效沟通。 首先,理解JavaScript(JS)和Java的运行环境差异至关重要。JS主要在浏览器环境中运行,负责处理用户交互和动态内容,而...
2. 类加载机制:双亲委派模型和自定义类加载器。 3. 性能调优:JVM参数设置,如堆内存、栈内存、 PermGen/Metaspace 等。 十、Java高级特性 1. Lambda表达式:函数式编程的引入,理解函数式接口和流API。 2. Stream...
- 静态变量在类加载时被初始化,所有类的对象共享同一份静态变量的副本。 - 静态方法不依赖于任何特定对象,可以直接通过类名调用,无法访问非静态成员。 4. **final修饰符**: - `final`用于声明不可改变的变量...
自定义日志文件类; 8线程 线程的启动 和停止;线程的互斥;线程的协作;线程join;生产者、消费者问题;线程的优先级;列出虚拟机中所有的线程;守护线程Daemon;线程池;一个死锁的例子; 定时器Timer:包括在指定...
JavaQQ 是一个基于Java编程语言实现的即时通讯软件,它具备了私聊、群聊、截图和文件传输等核心功能,旨在提供与QQ类似的用户体验。这个项目不仅展示了Java在开发复杂应用程序上的能力,还体现了面向对象设计原则和...
### JAVA复习题及答案知识点解析 #### 一、选择题知识点解析 1. **所有类的根类** - **知识点**: 在Java中,所有类都直接或间接继承自`java.lang.Object`类。 - **解析**: Java 的类层次结构是从`Object`类开始...
在IT行业中,XML(eXtensible Markup Language)是一种用于标记数据的标准格式,它具有良好的结构性和可读性,广泛应用于数据交换、配置文件以及在不同系统间传递信息。Java作为一个强大的开发平台,提供了丰富的API...
在Java中,Socket类代表了客户端到服务器的连接,并通过输入/输出流进行数据交换。 2. **Android Socket编程**: - 在Android上实现Socket通信需要处理权限问题,通常需要在AndroidManifest.xml中添加`INTERNET`...
5. **Java.awt.dnd**: Drag and Drop功能的实现,提供了DragGestureListener、DragSource和DropTarget等接口和类,使得用户可以通过拖放操作来传递数据。 6. **Java.awt.event**: 提供了处理AWT组件产生的各种事件...
首先,`zeromq.jar` 文件是ZeroMQ Java API的二进制库,它允许Java开发者通过调用Java类和方法来利用ZeroMQ的功能。这个JAR文件包含了ZeroMQ的核心功能,如创建套接字(sockets)、发送和接收消息、设置连接选项等。...