0
点赞
收藏
分享

微信扫一扫

使用java进行网络编程(二)


使用java进行网络编程(二)

远程通讯协议的基本原理

  网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http 、 tcp 、 udp 等等, http 、 tcp 、 udp 都是在基于 Socket 概念上为某类应用场景而扩展出的传输协议,网络 IO ,主要有 bio 、 nio 、 aio 三种方式,所有的分布式应用通讯都基于这个原理而实现,只是为了应用的易用,各种语言通常都会提供一些更为贴近应用易用的应用层协议。

 

应用级协议Binary-RPC

  Binary-RPC(Remote Procedure Call Protocol,远程过程调用协议)是一种和RMI(Remote Method Invocation,远程方法调用)类似的远程调用的协议,它和RMI 的不同之处在于它以标准的二进制格式来定义请求的信息 ( 请求的对象、方法、参数等 ) ,这样的好处是什么呢,就是在跨语言通讯的时候也可以使用。

  Binary -RPC 协议的一次远程通信过程:

  1 、客户端发起请求,按照 Binary -RPC 协议将请求信息进行填充;

  2 、填充完毕后将二进制格式文件转化为流,通过传输协议进行传输;

  3 、接收到在接收到流后转换为二进制格式文件,按照 Binary -RPC 协议获取请求的信息并进行处理;

  4 、处理完毕后将结果按照 Binary -RPC 协议写入二进制格式文件中并返回。

问题总结:

  1 、传输的标准格式是:标准格式的二进制文件。

  2 、怎么样将请求转化为传输的流?将二进制格式文件转化为流。

  3 、怎么接收和处理流?通过监听的端口获取到请求的流,转化为二进制文件,根据协议获取请求的信息,进行处理并将结果写入 XML 中返回。

  4 、传输协议是?http

 

Hessian

Hessian是一个轻量级的remoting on http工具,采用的是Binary RPC协议,所以它很适合于发送二进制数据,同时又具有防火墙穿透能力。Hessian一般是通过Web应用来提供服务,因此非常类似于平时我们用的 WebService。只是它不使用SOAP协议,但相比webservice而言更简单、快捷。

Hessian官网:http://hessian.caucho.com/

Hessian 可通过Servlet提供远程服务,需要将匹配某个模式的请求映射到Hessian服务。也可Spring框架整合,通过它的 DispatcherServlet可以完成该功能,DispatcherServlet可将匹配模式的请求转发到Hessian服务。Hessian的server端提供一个servlet基类, 用来处理发送的请求,而Hessian的这个远程过程调用,完全使用动态代理来实现的,,建议采用面向接口编程,Hessian服务通过接口暴露。

Hessian处理过程示意图:客户端——>序列化写到输出流——>远程方法(服务器端)——>序列化写到输出流 ——>客户端读取输入流——>输出结果

 

下载Hessian

  去Hessian官网:http://hessian.caucho.com/下载最新的Hessian包,如下图所示:

  

使用java进行网络编程(二)_客户端

  下载完成之后,得到如下图所示的jar文件

  

使用java进行网络编程(二)_客户端_02

 

搭建Hessian测试服务端web项目

  新建一个名为HessianServer的web project。将hessian-4.0.37.jar放入WEB-INF/lib文件夹中,如下图所示:

  

使用java进行网络编程(二)_User_03

  在进行基于Hessian的项目开发时,应当注意以下几点:

  JAVA服务器端必须具备以下几点:

  1. 包含Hessian的jar包。
  2. 设计一个接口,用来给客户端调用。
  3. 实现该接口的功能。
  4. 配置web.xml,配好相应的servlet。
  5. 对象必须实现Serializable 接口。
  6. 对于复杂对像可以使用Map的方法传递。

  客户端必须具备以下几点:

  1. java客户端包含Hessian.jar的包。
  2. 具有和服务器端结构一样的接口。
  3. 利用HessianProxyFactory调用远程接口。

设计一个提供服务接口来给客户端调用

IService接口的代码如下:

package gacl.hessian.service;
  
  import gacl.hessian.model.User;
  
  /**
   * <p>ClassName: IService<p>
   * <p>Description: 定义对外提供服务的接口<p>
   * @author xudp
  * @version 1.0 V
  * @createTime 2014-8-7 下午05:29:23
  */
 public interface IService { 
     /**
      * MethodName: getUser
      * Description: 获取用户
      * @return User      */
     public User getUser();
 }

  IService接口中用到了一个User类

User类的代码如下:

package gacl.hessian.model;
 
 import java.io.Serializable;
  
 /**
  * <p>ClassName: User<p>
  * <p>Description: 创建一个User类,实现序列化接口,
  * User实现了序列化接口后就可以进行序列化,
  * 然后就可以通过网络将序列化后的user传输到另一台计算机上<p>
  * @author xudp
  * @version 1.0 V
  * @createTime 2014-8-7 下午05:25:09
  */
 public class User implements Serializable{
 
     private static final long serialVersionUID = 1692800630322115854L;
     //name属性
     private String name;
 
     public User() {
         
     }
 
     public User(String name) {
         this.name = name;
     }
 
     public String getName() {
         return name;
     }
 
     public void setName(String name) {
         this.name = name;
     }
     
     
 }

编写IService接口的具体实现类

  ServiceImpl实现类的代码如下:

package gacl.hessian.service.impl;
 
 import gacl.hessian.model.User;
 import gacl.hessian.service.IService;
 
 /**
  * <p>ClassName: ServiceImpl<p>
  * <p>Description: IService接口的具体实现类<p>
  * @author xudp
  * @version 1.0 V
  * @createTime 2014-8-7 下午05:32:15
  */
 public class ServiceImpl implements IService {
 
     /* (non-Javadoc)
      * @MethodName getUser
      * @Description 实现IService接口的getUser方法
      * @author xudp
      * @return 返回一个User对象
      * @see gacl.hessian.service.IService#getUser()
      */
     public User getUser() {
         return new User("孤傲苍狼");
     }
 }

配置web.xml,添加对HessianServlet的配置

如下面的红色部分所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <welcome-file-list>
         <welcome-file>index.jsp</welcome-file>
     </welcome-file-list>
 
    <servlet>
         <!-- 配置 HessianServlet,Servlet的名字随便配置,例如这里配置成ServiceServlet-->
         <servlet-name>ServiceServlet</servlet-name>
         <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
         
         <!-- 配置接口的具体实现类 -->
         <init-param>
             <param-name>service-class</param-name>
             <param-value>gacl.hessian.service.impl.ServiceImpl</param-value>
         </init-param>
     </servlet>
     <!-- 映射 HessianServlet的访问URL地址-->
     <servlet-mapping>
         <servlet-name>ServiceServlet</servlet-name>
         <url-pattern>/ServiceServlet</url-pattern>
     </servlet-mapping>
 
 </web-app>

 到此,Hessian的服务端编写就算是完成了。

  配置完成之后,启动项目,在地址栏输入:http://localhost:端口号/项目名/ServiceServlet,如果显示结果如下,说明配置和接口编写正确:

  Hessian Requires POST

使用java进行网络编程(二)_使用java进行网络编程(二)_04

 

编写Hessian的测试客户端

  新建一个HessianTestClient的普通Java项目作为测试客户端,需引入上述的hessian-4.0.37.jar,还需要服务端导出IService和User两个类的jar,放入lib。或创建两个一摸一样的类,这里是采用将服务端的IService和User两个类打包成jar包提供给客户端进行调用,打成Jar包的过程如下图所示:

选中要打包的类

使用java进行网络编程(二)_java_05

使用java进行网络编程(二)_java_06

使用java进行网络编程(二)_使用java进行网络编程(二)_07

  这样就将IService类和User类打包成了一个Hessian_Common.jar包,如下图所示:

 

使用java进行网络编程(二)_客户端_08

  创建好的HessianTestClient工程如下所示:

  

使用java进行网络编程(二)_java_09

  HessianTestClient项目引入上述的hessian-4.0.37.jar和IService和User两个类的jar,编写HessianClient客户端,HessianClient类的代码如下所示:

package hessian.test.client;
 
 import java.net.MalformedURLException;
 
 import gacl.hessian.model.User;
 import gacl.hessian.service.IService;
 
 import com.caucho.hessian.client.HessianProxyFactory;
 
 /**
  * <p>ClassName: HessianClient<p>
  * <p>Description: 调用Hessian的客户端<p>
  * @author xudp
 * @version 1.0 V
  * @createTime 2014-8-7 下午07:05:42
  */
 public class HessianClient {
 
     public static void main(String[] args) throws MalformedURLException {
         /* 
             <servlet>
                 <!-- 配置 HessianServlet,Servlet的名字随便配置,例如这里配置成ServiceServlet-->
                 <servlet-name>ServiceServlet</servlet-name>
                 <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
                 
                 <!-- 配置接口的具体实现类 -->
                <init-param>
                    <param-name>service-class</param-name>
                     <param-value>gacl.hessian.service.impl.ServiceImpl</param-value>
                 </init-param>
             </servlet>
             <!-- 映射 HessianServlet的访问URL地址-->
             <servlet-mapping>
                 <servlet-name>ServiceServlet</servlet-name>
                 <url-pattern>/ServiceServlet</url-pattern>
             </servlet-mapping>
          */
         //在服务器端的web.xml文件中配置的HessianServlet映射的访问URL地址
         String url = "http://192.168.1.144:8080/HessianServer/ServiceServlet";
         HessianProxyFactory factory = new HessianProxyFactory();
         IService service = (IService) factory.create(IService.class, url);//创建IService接口的实例对象
         User user = service.getUser();//调用Hessian服务器端的ServiceImpl类中的getUser方法来获取一个User对象
         System.out.println(user.getName());
    }
 }

  将HessianServer项目部署到tomcat服务器,启动tomcat服务器,然后运行HessianClient客户端,运行结果如下:

  

使用java进行网络编程(二)_使用java进行网络编程(二)_10

  从运行结果中可以看到,在HessianClient客户端中已经成功获取到远程的HessianServer服务器端传输过来的User对象,然后打印出User对象的名字。

  以上就是Hessian的一个入门级别的案例!

 

使用hessian上传文件

essian较早版本通过 byte[] 进行文件传输;4.0之后支持 InputStream 作为参数或返回值进行传输。 
  注意:hessian会读取整个文件,如果文件过大,会导致JVM内存溢出。可以通过控制上传文件的大小,设置合理的JVM参数,以及采用随机读取方式来解决。

创建Hessian服务端

  创建一个FileUploader Web项目作为文件上传的服务端,如下图所示:

  

使用java进行网络编程(二)_java_11

创建文件上传服务接口FileUploadServiceI

  FileUploadServiceI接口代码如下:

package file.upload.service;
 
 import java.io.InputStream;
 
 /**
  * <p>ClassName: FileUploadServiceI<p>
  * <p>Description: 文件上传服务接口<p>
  * @author xudp
  * @version 1.0 V
  * @createTime 2014-8-8 上午10:41:27
  */
 public interface FileUploadServiceI {
 
     public void upload(String filename, InputStream data);
 }

实现文件上传服务接口FileUploadServiceI

   FileUploadServiceImpl类的代码如下:

package file.upload.service.impl;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
 import file.upload.service.FileUploadServiceI;
 
 /**
  * <p>ClassName: FileUploadServiceImpl<p>
  * <p>Description: FileUploadServiceI文件上传接口的具体实现类<p>
  * @author xudp
  * @version 1.0 V
  * @createTime 2014-8-8 上午10:42:43
  */
 public class FileUploadServiceImpl implements FileUploadServiceI {
 
     /* (non-Javadoc)
      * @MethodName upload
      * @Description 上传文件
      * @author xudp
      * @param filename 上传的文件名
      * @param data 上传的文件的输入流
      * @see file.upload.service.FileUploadServiceI#upload(java.lang.String, java.io.InputStream)
      */
     public void upload(String filename, InputStream data) {
         BufferedInputStream bis = null;
         BufferedOutputStream bos = null;
         try {
             //获取客户端传递的InputStream
             bis = new BufferedInputStream(data);
             //创建文件输出流
             bos = new BufferedOutputStream(new FileOutputStream(
                     "E:/fileUpload/" + filename));
             byte[] buffer = new byte[8192];
             int r = bis.read(buffer, 0, buffer.length);
             while (r > 0) {
                 bos.write(buffer, 0, r);
                 r = bis.read(buffer, 0, buffer.length);
             }
             System.out.println("-------文件上传成功!-------------");
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             if (bos != null) {
                 try {
                     bos.close();
                 } catch (IOException e) {
                     throw new RuntimeException(e);
                 }
             }
             if (bis != null) {
                 try {
                     bis.close();
                 } catch (IOException e) {
                     throw new RuntimeException(e);
                 }
            }
         }
     }
 
 }

在web.xml中配置HessianServlet

<?xml version="1.0" encoding="UTF-8"?>
 <web-app version="2.5" 
      xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <servlet>
     <servlet-name>FileUploadService</servlet-name>
     <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
     <init-param>
     <!-- home-class也可以写为service-class -->
       <param-name>home-class</param-name>
       <!-- 服务器对接口的现实,供客户端调用 --> 
       <param-value>file.upload.service.impl.FileUploadServiceImpl</param-value>
     </init-param>
     <init-param>
     
     <!--
         提供给客户端调用的接口,这里的home-api配置不是必须的,可以不配置
     -->
     <!--home-api也可以写为api-class  -->
       <param-name>home-api</param-name>
       <!-- 客户端接口 -->
       <param-value>file.upload.service.FileUploadServiceI</param-value>
     </init-param>
   </servlet>
   <servlet-mapping>
     <servlet-name>FileUploadService</servlet-name>
     <url-pattern>/FileUploadService</url-pattern>
   </servlet-mapping>
   
 </web-app>

 到此,服务端的编写就完成了,部署FileUploader到Tomcat服务器,启动Tomcat服务器,在浏览器地址栏输入:http://localhost:8080/FileUploader/FileUploadService,查看是否可以调用。

使用java进行网络编程(二)_User_12

  看到这样的运行结果就说明Hessian服务器的测试通过。

 

创建文件上传客户端

  创建一个普通的java项目作为文件上传客户端,添加对hessian-4.0.37.jar的引用,同时将Hessian服务端的FileUploadServiceI接口打包成jar包提供给文件上传客户端调用,如下图所示:

 

使用java进行网络编程(二)_客户端_13

编写文件上传客户端

  FileUploaderClient类的代码如下:

package file.uplaod.client;
 
 import java.io.BufferedInputStream;
 import java.io.FileInputStream;
 import java.io.InputStream;
 import com.caucho.hessian.client.HessianProxyFactory;
 import file.upload.service.FileUploadServiceI;
 
 /**
  * <p>ClassName: FileUploaderClient<p>
  * <p>Description: 文件上传客户端<p>
  * @author xudp
  * @version 1.0 V
  * @createTime 2014-8-8 上午10:00:13
  */
 public class FileUploaderClient {
      //Hessian服务的url
      private static final String url = "http://gacl:8080/FileUploader/FileUploadService";
 
    public static void main(String[] args) throws Exception {
         //创建HessianProxyFactory实例
         HessianProxyFactory factory = new HessianProxyFactory();
         //获得Hessian服务的远程引用
         FileUploadServiceI uploader = (FileUploadServiceI) factory.create(FileUploadServiceI.class, url);
         //读取需要上传的文件
         InputStream data = new BufferedInputStream(new FileInputStream("E:/开发资料/电子书/Shiro教程.pdf"));
         //调用远程服务上传文件。
         uploader.upload("Shiro教程.pdf", data);
     }
 }

运行FileUploaderClient客户端,就可以将文件"Shiro教程.pdf"上传到服务器上的指定存储目录了,如下图所示:

  

使用java进行网络编程(二)_User_14

 

 

举报

相关推荐

0 条评论