所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链句柄。应用程序通常经过"套接字"向网络发出请求或应答网络请求。
Socket和ServerSocket类库在java.net包中。
ServerSocket用于服务器端,Socket 是建立网络连接时使用。在连接成功时,应用程序两端全部会产生一个Socket实例,操作这个实例,完成所需会话。对于一个网络连接来说,套接字是平等,并没有差异,不因为在服务器端或在用户端而产生不一样等级。
不管是Socket还是ServerSocket它们工作全部是经过SocketImpl类及其子类完成。
服务器端: ServerDemo.java package com.lanber.socket; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class ServerDemo { |
: |
//服务器向用户端发送连接成功确定信息 dos.writeUTF("接收连接请求, 连接成功!"); //不需要继续使用此连接时, 关闭连接 } |
用户端:ClientDemo.java
package com.lanber.socket; import java.io.DataInputStream; public class ClientDemo { |
/**
DataOutputStream(socket.getOutputStream()); //获取输入流, 用于接收服务器端发送来数据
DataInputStream(socket.getInputStream()); //用户端向服务器端发送数据 |
e.printStackTrace(); } } |
|
RMI(RemoteMethod Invocation)远程方法调用是一个计算机之间利用远程对象相互调用实现双方通讯一个通讯机制。
使用这种机制,某一台计算机上对象能够调用另外一台计算机上对象来获取远程数据。RMI是Enterprise
JavaBeans支柱,是建立分布式Java应用程序方便路径。在过去,TCP/IP套接字通讯是远程通讯关键手段,但此开发方法没有使用面向对象方法实现开发,在开发一个如此通讯机制时往往令程序员感觉到乏味,对此RPC(RemoteProcedure Call)应运而生,它使程序员更轻易地调用远程程序,但在面对复杂信息传讯时,RPC仍然未能很好支持,
而且RPC 未能做到面向对象调用开发模式。 | 针对RPC 服 |
务遗留问题,RMI出现在世人面前,它被设计成一个面向对象通讯方法,许可程序员使用远程对象来实现通信,而且支持多线程服务,这是一次远程通讯,为远程通信开辟新里程碑。
RMI开发步骤
先创建远程接口及申明远程方法,注意这是实现双方通讯接口,需要继承Remote
开发一个类来实现远程接口及远程方法,值得注意是实现类需要继承UnicastRemoteObject
经过javac命令编译文件,经过java-server 命令注册服务,开启远程对象
最终用户端查找远程对象,并调用远程方法
简单实例
首先为服务建立一个Model层,注意因为此对象需要现实进行远程传输,所以必需继承Serializable
packagermi.model;
import java.io.Serializable; |
//注意对象必需继承Serializable
publicclass PersonEntity implements |
Serializable { | |||
| privateint id; | ||
|
| ||
| privateint age; | ||
|
| ||
| this.id = id; | ||
|
| ||
| publicint getId() { | ||
|
| ||
| } | ||
|
| ||
| this.name = name; | ||
|
| ||
| public String getName() { | ||
|
| ||
| } | ||
|
| ||
| this.age = age; | ||
|
| ||
| publicint getAge() { | ||
|
|
| } |
|
创建远程接口PersonService,注意远程接口需要继承
Remote
packagermi.service;
import java.rmi.Remote; |
importjava.rmi.RemoteException;
import java.util.List; |
importrmi.model.*;
| ||||
public | interface | PersonService extends | Remote |
{
| public List<PersonEntity> GetList() |
throws RemoteException; |
}
建立PersonServiceImpl实现远程接口,注意此为远程对象
实现类,需要继承UnicastRemoteObject
packagermi.serviceImpl;
import java.rmi.RemoteException; |
importjava.rmi.server.UnicastRemoteObject;
import java.util.LinkedList; |
importjava.util.List;
import rmi.model.PersonEntity; |
importrmi.service.*;
//此为远程对象实现类, 须继承 |
UnicastRemoteObject |
publicclassPersonServiceImpl extends
UnicastRemoteObject implements | PersonService { | ||
| public PersonServiceImpl() throws |
RemoteException { |
| super(); | |
| // TODO Auto-generated constructor |
stub | | ||
| } | ||
| @Override | ||
| public List<PersonEntity> GetList() |
throwsRemoteException {
| // TODO Auto-generated method stub | |
| System.out.println("Get Person |
Start!");
| List<PersonEntity> personList=new |
LinkedList<PersonEntity>(); |
|
| |
| PersonEntity person1=new |
PersonEntity(); | |||
| person1.setAge(25); | ||
|
| ||
| person1.setName("Leslie"); | ||
|
|
| | |
| PersonEntity person2=new |
PersonEntity(); |
| person2.setAge(25); | |
| person2.setId(1); | |
| person2.setName("Rose"); | |
| personList.add(person2); |
| | | ||
| |
| ||
| } | |
|
}
建立服务器端,在服务器端注册RMI通讯端口和通讯路径,然后通讯javac命令编译文件,经过java-server 命令注册服务。以下面代码为例,假如阁下将项目建立于
D://RMI/RemotingService文件夹上时,则先输入D://RMI/RemotingService/src>javac
rmi/remotingservice/Program.java获取Program.class(怎样阁下使用MyEclipse等开发工具,可跳过此步,直接在*/bin文件夹中直接调用已经生成Program.class),然后输入D://RMI/RemotingService/src>java
rmi/remotingservice/Program开启服务。
packagermi.remotingservice;
import java.rmi.Naming; |
importjava.rmi.registry.LocateRegistry;
|
importrmi.service.*;
import rmi.serviceImpl.*; |
publicclassProgram{
|
| ||
| // TODO Auto-generated method stub | ||
|
| ||
| PersonService personService=new |
PersonServiceImpl();
| //注册通讯端口 |
|
LocateRegistry.createRegistry(6600);
|
|
|
Naming.rebind("rmi://127.0.0.1:6600/PersonSer
vice",personService);
| System.out.println("Service |
Start!"); | ||
| } catch (Exception e) { | |
| // TODO Auto-generated catch block | |
| e.printStackTrace(); | |
| } | |
| } |
|
最终建立用户端进行测试,注意用户调用RMI路径必需服务
器配置一致
packagermi.remotingclient;
import java.rmi.Naming; |
importjava.util.List;
|
importrmi.service.*;
| |||
| publicstaticvoid main(String[] args){ | ||
|
| ||
| //调用远程对象, 注意RMI 路径和接口 |
必需和服务器配置一致
| PersonService |
personService=(PersonService)Naming.lookup("r |
mi://127.0.0.1:6600/PersonService"); | |
| List<PersonEntity> |
personList=personService.GetList();
| for(PersonEntity |
person:personList){ |
|
System.out.println("ID:"+person.getId()+"
Age:"+person.getAge()+"
Name:"+person.getName());
| |
| ||
| | }catch(Exception ex){ | ||
| |
| ||
| | } | ||
|
| |
}
|
Java&CORBA 编程实例 |
Java IDL 技术在Java 平台上添加了CORBA(Common Object |
Request Broker Architecture)功效, 提供了基于标准互操 |
作能力和连接性。Java IDL 技术使得分布式Java Web 应用能 |
够经过使用工业标准IDL 和IIOP(Internet Inter-ORB |
Protocol)来透明地调用远程网络服务操作。 运行时组件 |
(Runtime Components)包含了一个用于分布式计算且使用 |
IIOP 通信Java ORB. |
可移植对象适配器(Portable Object Adapter, POA) |
CORBA 对象负责分隔服务器端远程调用句柄 (handler)到远程对象和它服务者(servant)。 对象由远程调用所暴露, |
而服务者包含实际处理这些请求方法。 每个对象全部能够 |
选择服务者为静态(一次)或动态(每个远程调用),在这两种情况下,全部许可调用转移到另一台服务器。在服务器端,POA 形成了类似树状结构,每个POA全部负责一到多个服务对象。树分支能够是活动、 或钝化,服务者调用有不一样代码和不一样请求处理策略。
API规范
* org.omg.CORBA 包-提供了OMGCORBA APIs 到Java编程语言映射
* org.omg.CosNaming 包-为JavaIDL 提供命名服务 * org.omg.PortableServer 包-为建立服务器端可移植、跨越多ORB应用程序提供类和接口
* org.omg.PortableInterceptor 包-提供了注册ORB钩子机制,此钩子经过ORB服务能截取正常ORB实施流 * org.omg.DynamicAny 包-提供了使得任何值全部能被动态解释(或遍历)和经过DynAny对象结构出来类和接口
* org.omg.CORBA.ORB - 为CORBAORB 功效API
分布式对象之间关系有两方面:用户端和服务器。服务器提供远程接口,用户端调用远程接口。
在用户端,应用程序包含远程对象引用。该对象引用有
stub 方法, 它是远程方法。 stub 方法实际连接到ORB, |
所以调用它实际上转发调用到服务器。 |
在服务器端, ORB 使用skeleton 代码翻译远程调用为当地对 |
象方法调用。 Skeleton 把调用转换成指定实现格式, 并在方法中调用。 当方法返回时, Skeleton 代码转换方法调用结 |
果或错误, 经ORB 送回用户端。 |
Java IDL 开发过程 |
1)定义远程接口 |
使用IDL 语言为远程对象定义接口。 |
【Billing.idl 源代码】以下: |
// 申明CORBA IDL 模块 |
module BillingApp{ |
// 申明接口 |
interface Billing{ |
string successBilling(); |
oneway void shutdown(); |
}; |
}; |
2)编译远程接口 |
使用idlj编译器生成Java语言stub和skeleton源文件。
idlj 编译器缺省只生成用户端binding 代码。 假如同时需 |
要用户端bindings 和服务器端skeletons, 必需加上-fall |
选项。 |
使用POA(Portable Object Adaptor)优点: |
·许可编程者构建对象在不一样ORB产品之间可移植实现·支持带持久化标识对象
·对对象透明活动提供支持
·许可单个servant支持多个对象同时标识
注意:确定jdk/bin目录下有:idlj、java、javac、orbd命令:
idlj -fall Billing.idl
在目前目录下生成BillingApp目录,包含以下六个文件:
· Billing.java ————> 此接口包含IDL 接口Java版本。 它继承自org.omg.CORBA.Object, 提供标准CORBA 对 |
象功效。
·BillingHelper.java ————> 这类提供辅助功效,Helper 类负责读写数据类型到CORBA流,和插入和提取数据类型。
·BillingHolder.java ————> This final class holds apublic instance member of type Billing.
·BillingOperations.java ————>此接口包含successBilling()和shutdown()方法。
·BillingPOA.java ————> 此抽象类是基于流服务器Skeleton,为服务器提供基础CORBA功效。它继承
org.omg.PortableServer.Servant, 实现了 |
InvokeHandler接口和BillingOperations接口。 服务器类 |
BillingServant继承BillingPOA。
·_BillingStub.java ————> 这类是用户端stub,
为用户端提供CORBA 功效。 它继承org.omg.CORBA.Object, 提供标准CORBA 对象功效。 还扩展了 BillingOperations 接 |
口和org.omg.CORBA.portable.IDLEntity接口。
3)实现服务器端
一旦使用idlj编译器后,就能够使用它产生Skeleton装配服务器应用程序了。另外要实现远程接口方法,服务器代码应包含开启ORB和等候远程用户端调用机制。
服务器端由两个类组成,一个是servant,另一个是Server。
每个servant是BillingImpl类,是BillingIDL 接口实现,Billing 实例均由BillingImpl实例实现。servant是BillingPOA子类。
servant包含了IDL定义全部方法,和通常Java方法类似。
server类含服务器main()方法,它:
·创建和初始化ORB实例
·取得根POA引用并激活POAManager
·创建一个Servant实例(CORBABilling对象实现)并通知ORB
·取得根命名上下文
· 在命名上下文用“Billing”名注册新对象 |
· 等候用户端调用此新对象 |
【BillingImpl.java 源码】: |
importorg.omg.CORBA.ORB;
importBillingApp.*;
classBillingImpl extends BillingPOA{ private ORB orb;
public void setORB(ORB orb_val){ this.orb = orb_val;
}
public String successBilling() {
return "\nBilling success!!\n";
}
public void shutdown(){
orb.shutdown(false);
}
} |
|
importorg.omg.CORBA.ORB;
importorg.omg.CosNaming.NameComponent;
importorg.omg.CosNaming.NamingContextExt; import
org.omg.CosNaming.NamingContextExtHelper;
importorg.omg.PortableServer.POA;
importBillingApp.*;
publicclass BillingServer {
public static void main(String args[]){ try{
// 创建和初始化ORB
ORB orb = ORB.init(args, null);
// 取得根POA引用并激活POAManager
POA rootpoa =
(POA)orb.resolve_initial_references("RootPOA");
rootpoa.the_POAManager().activate(); |
// 创建servant 并注册到ORB |
BillingImplbillingImpl = new BillingImpl(); billingImpl.setORB(orb);
// 从servant取得对象引用
org.omg.CORBA.Object ref =
rootpoa.servant_to_reference(billingImpl);
Billing href = BillingHelper.narrow(ref); // 得到根命名上下文
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService"); // 使用命名上下文,它是互操作命名服务规范一部分
NamingContextExt ncRef =
NamingContextExtHelper.narrow(objRef);
// 在命名中绑定对象引用
String name = "Billing";
NameComponent path[] = ncRef.to_name(name); ncRef.rebind(path, href);
System.out.println("BillingServer is ready and waiting...");
// 等候用户端调用
orb.run(); |
}catch(Exception e){ |
System.err.println("ERROR:"+e); |
e.printStackTrace(System.out); |
} |
System.out.println("BillingServer |
Exiting ..."); |
} |
} |
4)实现用户端 |
和第三步类似, 能够使用idlj 产生stub 作为用户端应用程 |
序基础。 用户端代码建立于stub 之上, 开启ORB, 使用服务 |
器提供命名服务查询, 取得远程对象引用, 调用其方法。 |
【BillingClient.java 源码】: |
import org.omg.CORBA.ORB; |
import org.omg.CosNaming.NamingContextExt; |
import |
org.omg.CosNaming.NamingContextExtHelper; |
import BillingApp.*; |
public class BillingClient { |
static Billing billingImpl; |
public static void main(String args[]){ |
try{ |
// 创建和初始化ORB |
ORBorb = ORB.init(args, null);
System.out.println("ORB initialised");
// 取得根命名上下文
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService"); // 使用NamingContextExt替换命名上下文,它是互操作命名服务一部分
NamingContextExt ncRef =
NamingContextExtHelper.narrow(objRef);
// 在命名中解析对象引用
String name = "Billing";
billingImpl =
BillingHelper.narrow(ncRef.resolve_str(name));
System.out.println("Obtained a handle on server object:"+billingImpl);
System.out.println(billingImpl.successBilling()); billingImpl.shutdown();
}catch(Exception e){
System.out.println("ERROR: "+e); |
e.printStackTrace(System.out); |
} |
} |
} |
5)开启应用程序 |
要运行服务器和用户端, 必需先开启命名服务, 再开启服务 |
器, 最终运行用户端。 |
此例用到命名服务, 它使得servant对象操作对用户端有效。 |
服务器需要命名服务对象引用, 命名服务能够公布对象引用 |
实现多种接口。 用户端使用对象引用来调用方法。 |
Copyright © 2019- xiaozhentang.com 版权所有 湘ICP备2023022495号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务