`

java socket类文件传递及加载

 
阅读更多

最近遇到一个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;
	}
}

 

0
2
分享到:
评论

相关推荐

    java socket多人聊天(文字+图片+文件传输)

    在Java中,`java.net.Socket`类和`java.net.ServerSocket`类用于创建客户端和服务器端的Socket连接。在这个聊天应用中,服务器端使用`ServerSocket`监听特定端口,等待客户端的连接请求;客户端则使用`Socket`与...

    android中java和C的socket通信demo

    本教程将详细解释如何在Android中实现Java和C的Socket通信,特别是在涉及文件描述符传递的场景下。 1. **Java Socket基础** Java中的`java.net.Socket`类提供了网络通信的能力,它允许我们在两个应用程序之间建立...

    java的基于Socket的文件传输服务

    Java中的基于Socket的文件传输服务是一种通过网络进行文件交互的方式,它利用了TCP/IP协议栈中的Socket接口。在Java中,Socket是网络通信的基础,它提供了应用程序与网络之间的连接通道,使得两个网络节点(通常是...

    java与c++传文件程序

    本项目实现了一个基于Socket的文件传输方案,其中Java作为服务端,C++作为客户端,使得Windows环境下的文件能够在两个程序之间安全、高效地传递。以下是对这个程序设计和实现的关键知识点的详细说明: 1. **Java ...

    socket客户端长连接实现以及xml文件解析

    1. **创建Socket对象**:在客户端,使用`java.net.Socket`类创建一个Socket实例,指定服务器的IP地址和端口号。 2. **建立连接**:调用`Socket`对象的`connect()`方法,向服务器发起连接请求。 3. **数据传输**:...

    Socket通信 能够发送文件,实体类,字符串等多种发送方式

    在Java中,Socket通信基于TCP/IP协议栈,提供了稳定的数据传输能力,能够支持多种数据类型如文件、实体类和字符串的发送。本节将深入探讨Socket通信的工作原理、如何发送不同类型的 data以及其在实际项目中的应用。 ...

    java 传送文件

    首先,Java提供了Socket编程接口来实现网络通信,包括文件传输。在服务器端,我们需要创建一个ServerSocket监听特定的端口,等待客户端连接。以下是一个简单的服务器端代码片段: ```java import java.io.*; import...

    Socket网络编程之文件上传下载源码

    在这个场景中,我们将深入探讨如何使用Java的Socket API实现文件的上传和下载功能。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它为上层应用提供了稳定的数据...

    利用socket实现双机通信.

    首先,Java中的Socket类代表了网络上的一个端点,而ServerSocket类用于监听客户端的连接请求。在双机通信中,通常一台机器作为服务器(Server),另一台作为客户端(Client)。服务器需要先启动并监听特定的端口,...

    ZeroMQ及java绑定

    导入这个JAR文件到Java项目中,开发者就可以在Java代码中方便地使用ZeroMQ的功能,例如创建socket、设置socket选项、发送和接收消息等。 在描述中提到的"已经编译了zeromq及jzmq"意味着,这些文件都是预先编译好的...

    js调用java类的方法

    本文将深入探讨如何使用JavaScript调用Java类的方法,以实现客户端和服务器端的有效沟通。 首先,理解JavaScript(JS)和Java的运行环境差异至关重要。JS主要在浏览器环境中运行,负责处理用户交互和动态内容,而...

    java笔试宝典(rar文件)

    2. 类加载机制:双亲委派模型和自定义类加载器。 3. 性能调优:JVM参数设置,如堆内存、栈内存、 PermGen/Metaspace 等。 十、Java高级特性 1. Lambda表达式:函数式编程的引入,理解函数式接口和流API。 2. Stream...

    完整版 Java基础入门教程 Java程序语言设计 03 java对象 类与对象2(共23页).ppt

    - 静态变量在类加载时被初始化,所有类的对象共享同一份静态变量的副本。 - 静态方法不依赖于任何特定对象,可以直接通过类名调用,无法访问非静态成员。 4. **final修饰符**: - `final`用于声明不可改变的变量...

    java jdk实列宝典 光盘源代码

    自定义日志文件类; 8线程 线程的启动 和停止;线程的互斥;线程的协作;线程join;生产者、消费者问题;线程的优先级;列出虚拟机中所有的线程;守护线程Daemon;线程池;一个死锁的例子; 定时器Timer:包括在指定...

    javaqq(私聊+群聊+截图+文件传送)

    JavaQQ 是一个基于Java编程语言实现的即时通讯软件,它具备了私聊、群聊、截图和文件传输等核心功能,旨在提供与QQ类似的用户体验。这个项目不仅展示了Java在开发复杂应用程序上的能力,还体现了面向对象设计原则和...

    JAVA复习题及答案

    ### JAVA复习题及答案知识点解析 #### 一、选择题知识点解析 1. **所有类的根类** - **知识点**: 在Java中,所有类都直接或间接继承自`java.lang.Object`类。 - **解析**: Java 的类层次结构是从`Object`类开始...

    JAVA XML \ 定长报文 与domino转换及通讯

    在IT行业中,XML(eXtensible Markup Language)是一种用于标记数据的标准格式,它具有良好的结构性和可读性,广泛应用于数据交换、配置文件以及在不同系统间传递信息。Java作为一个强大的开发平台,提供了丰富的API...

    基于socket的Anroid 聊天程序

    在Java中,Socket类代表了客户端到服务器的连接,并通过输入/输出流进行数据交换。 2. **Android Socket编程**: - 在Android上实现Socket通信需要处理权限问题,通常需要在AndroidManifest.xml中添加`INTERNET`...

    javaApi分类[参考].pdf

    5. **Java.awt.dnd**: Drag and Drop功能的实现,提供了DragGestureListener、DragSource和DropTarget等接口和类,使得用户可以通过拖放操作来传递数据。 6. **Java.awt.event**: 提供了处理AWT组件产生的各种事件...

    zeromq forJava的.jar包 和dll文件

    首先,`zeromq.jar` 文件是ZeroMQ Java API的二进制库,它允许Java开发者通过调用Java类和方法来利用ZeroMQ的功能。这个JAR文件包含了ZeroMQ的核心功能,如创建套接字(sockets)、发送和接收消息、设置连接选项等。...

Global site tag (gtag.js) - Google Analytics