基于Java自身包实现消息方式的系统间通信的方式有:TCP/IP+BIO,TCP/IP+NIO,UDP/IP+BIO,UDP/IP+NIO.下面就这4种类型一一做个详细的介绍:

一.TCP/IP+BIO

在java中可基于Socket,ServerSocket来实现TCP/IP+BIO的系统间通信。Socket主要用于实现建立连接以及网络IO的操作,ServerSocket主要用于实现服务器端端口的监听及Socket对象的获取。基于Socket实现客户端的代码如下:

public class Client {

    /**
* @param args
*/
public static void main(String[] args) throws Exception{
String host="127.0.0.1";
int port=9527;
Socket socket=new Socket(host,port);
BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out=new PrintWriter(socket.getOutputStream(),true);
BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
boolean flag=true;
while(flag){
String command=systemIn.readLine();
if(command==null || "quit".equalsIgnoreCase(command.trim())){
flag=false;
System.out.println("Client quit!");
out.println("quit");
out.close();
in.close();
socket.close();
continue;
}
out.println(command);
String response=in.readLine();
System.out.println(response);
}
} }

服务器端代码如下:

public class Server {

    /**
* @param args
*/
public static void main(String[] args) throws Exception{
int port=9527;
ServerSocket ss=new ServerSocket(port);
System.out.println("Server listen on port: "+port);
Socket socket=ss.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out=new PrintWriter(socket.getOutputStream(),true);
while(true){
String line=in.readLine();
if(line==null){
Thread.sleep(100);
continue;
}
if("quit".equalsIgnoreCase(line.trim())){
in.close();
out.close();
ss.close();
System.out.println("Server has been shutdown!");
System.exit(0);
}
else{
System.out.println("Message from client: "+ line);
out.println("Server response:"+line);
Thread.sleep(100);
}
}
} }

上面是基于Socket,ServerSocket实现的一个简单的系统间通信的例子。而在实际的系统中,通常要面对的是客户端同时要发送多个请求到服务器端,服务器端则同时要接受多个连接发送的请求,上面的代码显然是无法满足的。

为了满足客户端能同时发送多个请求到服务器端,最简单的方法就是生成多个Socket。但这里会产生两个问题:一是生成太多的Socket会消耗过多的本地资源,在客户端机器多,服务器端机器少的情况下,客户端生成太多Socket会

导致服务器端须要支撑非常高的连接数;二是生成Socket(建立连接)通常是比较慢的,因此频繁的创建会导致系统性能不足。鉴于这两个问题,通常采用连接池的方法来维护Socket是比较好的,一方面限制了能创建的Socket的个数;

另一个方面由于将Socket放入了池中,避免了重复创建Socket带来的性能下降的问题。数据库连接池就是这种方式的典型代表,但连接池的方式会带来另一个问题,连接池中的Socket的个数是有限的,但同时要用socket的请求可能会

很多,在这种情况下就会造成激烈的竞争和等待,还有一个需要注意的问题是合理控制等待响应的超时时间,如不设定会导致当服务器端处理变慢时,客户端相关的请求都在做无限的等待,二客户端的资源必然是有限的。因此这种情况

下很容易造成服务器端出问题时,客户端挂掉的现象。超时时间具体设置为多少取决于客户端能承受的请求量及服务器端的处理时间。既要保证性能,又要保证出错率不会过高,对于直接基于TCP/IP+BIO的方式,可采用Socket.setSotimeout来设置等待响应的超时时间。

二.TCP/IP+NIO

在java中可基于java.nio.channels中的Channel和Selector的相关类来实现TCP/IP+NIO方式的系统间通信。Channel有SocketChannel和ServerSocketChannnel两种,SocketChannel用于建立连接,监听事件及操作读写,

ServerSocketChannel用于监听端口及监听连接事件;程序通过Selector来获取是否有要处理的事件。基于这两个类实现客户端代码如下:

public class Client {

    public static void main(String[] args) throws Exception{
int port=9527;
SocketChannel channel=SocketChannel.open();
channel.configureBlocking(false);
SocketAddress target=new InetSocketAddress("127.0.0.1",port);
channel.connect(target);
Selector selector=Selector.open();
channel.register(selector, SelectionKey.OP_CONNECT);
BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
while(true){
if(channel.isConnected()){
String command=systemIn.readLine();
channel.write(Charset.forName("UTF-8").encode(command));
if(command==null || "quit".equalsIgnoreCase(command.trim())){
systemIn.close();
channel.close();
selector.close();
System.out.println("Client quit!");
System.exit(0);
}
}
int nKeys=selector.select(1000);
if(nKeys>0){
for (SelectionKey key : selector.selectedKeys()) {
if(key.isConnectable()){
SocketChannel sc=(SocketChannel) key.channel();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
sc.finishConnect();
}
else if(key.isReadable()){
ByteBuffer buffer=ByteBuffer.allocate(1024);
SocketChannel sc=(SocketChannel) key.channel();
int readBytes=0;
try{
int ret=0;
try{
while((ret=sc.read(buffer))>0){
readBytes+=ret;
}
}
finally{
buffer.flip();
}
if(readBytes>0){
System.out.println(Charset.forName("UTF-8").decode(buffer).toString());
buffer = null;
}
}
finally{
if(buffer!=null){
buffer.clear();
}
}
}
}
selector.selectedKeys().clear();
}
}
} }

服务器端代码如下:

public class Server {

    public static void main(String[] args) throws Exception{
int port=9527;
Selector selector=Selector.open();
ServerSocketChannel ssc=ServerSocketChannel.open();
ServerSocket serverSocket=ssc.socket();
serverSocket.bind(new InetSocketAddress(port));
System.out.println("Server listen on port: "+port);
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
while(true){
int nKeys=selector.select(1000);
if(nKeys>0){
for (SelectionKey key : selector.selectedKeys()) {
if(key.isAcceptable()){
ServerSocketChannel server=(ServerSocketChannel) key.channel();
SocketChannel sc=server.accept();
if(sc==null){
continue;
}
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
}
else if(key.isReadable()){
ByteBuffer buffer=ByteBuffer.allocate(1024);
SocketChannel sc=(SocketChannel) key.channel();
int readBytes=0;
String message=null;
try{
int ret;
try{
while((ret=sc.read(buffer))>0){
readBytes+=ret;
}
}
catch(Exception e){
readBytes=0;
// IGNORE
}
finally{
buffer.flip();
}
if(readBytes>0){
message=Charset.forName("UTF-8").decode(buffer).toString();
buffer = null;
}
}
finally{
if(buffer!=null){
buffer.clear();
}
}
if(readBytes>0){
System.out.println("Message from client: "+ message);
if("quit".equalsIgnoreCase(message.trim())){
sc.close();
selector.close();
System.out.println("Server has been shutdown!");
System.exit(0);
}
String outMessage="Server response:"+message;
sc.write(Charset.forName("UTF-8").encode(outMessage));
}
}
}
selector.selectedKeys().clear();
}
}
} }

三.UDP/IP+BIO

服务器端代码如下:

public class Server {

    /**
* @param args
*/
public static void main(String[] args) throws Exception{
int port=9527;
int aport=9528;
DatagramSocket server=new DatagramSocket(port);
DatagramSocket client=new DatagramSocket();
InetAddress serverAddress=InetAddress.getByName("localhost");
byte[] buffer=new byte[65507];
DatagramPacket packet=new DatagramPacket(buffer,buffer.length);
while(true){
server.receive(packet);
String line=new String(packet.getData(),0,packet.getLength(),"UTF-8");
if("quit".equalsIgnoreCase(line.trim())){
server.close();
System.exit(0);
}
else{
System.out.println("Message from client: "+ line);
packet.setLength(buffer.length);
String response="Server response"+line;
byte[] datas=response.getBytes("UTF-8");
DatagramPacket responsePacket=new DatagramPacket(datas,datas.length,serverAddress,aport);
client.send(responsePacket);
Thread.sleep(100);
}
}
} }

客户端代码如下:

public class Client {

    /**
* @param args
*/
public static void main(String[] args) throws Exception{
int port=9527;
int aport=9528;
DatagramSocket serverSocket=new DatagramSocket(aport);
byte[] buffer=new byte[65507];
DatagramPacket receivePacket=new DatagramPacket(buffer,buffer.length);
DatagramSocket socket=new DatagramSocket();
InetAddress server=InetAddress.getByName("localhost");
BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
boolean flag=true;
while(flag){
String command=systemIn.readLine();
byte[] datas=command.getBytes("UTF-8");
DatagramPacket packet=new DatagramPacket(datas,datas.length,server,port);
socket.send(packet);
if(command==null || "quit".equalsIgnoreCase(command.trim())){
flag=false;
System.out.println("Client quit!");
socket.close();
continue;
}
serverSocket.receive(receivePacket);
String receiveResponse=new String(receivePacket.getData(),0,receivePacket.getLength(),"UTF-8");
System.out.println(receiveResponse);
}
} }

四.UDP/IP+NIO

服务器端代码如下:

public class Server {

    public static void main(String[] args) throws Exception{
int rport=9527;
int sport=9528; DatagramChannel sendChannel=DatagramChannel.open();
sendChannel.configureBlocking(false);
SocketAddress target=new InetSocketAddress("127.0.0.1",sport);
sendChannel.connect(target); DatagramChannel receiveChannel=DatagramChannel.open();
DatagramSocket serverSocket=receiveChannel.socket();
serverSocket.bind(new InetSocketAddress(rport));
System.out.println("Data receive listen on port: "+rport);
receiveChannel.configureBlocking(false);
Selector selector=Selector.open();
receiveChannel.register(selector, SelectionKey.OP_READ);
while(true){
int nKeys=selector.select(1000);
if(nKeys>0){
for (SelectionKey key : selector.selectedKeys()) {
if(key.isReadable()){
ByteBuffer buffer=ByteBuffer.allocate(1024);
DatagramChannel dc=(DatagramChannel) key.channel();
dc.receive(buffer);
buffer.flip();
String message=Charset.forName("UTF-8").decode(buffer).toString();
System.out.println("Message from client: "+ message);
if("quit".equalsIgnoreCase(message.trim())){
dc.close();
selector.close();
sendChannel.close();
System.out.println("Server has been shutdown!");
System.exit(0);
}
String outMessage="Server response��"+message;
sendChannel.write(Charset.forName("UTF-8").encode(outMessage));
}
}
selector.selectedKeys().clear();
}
}
} }

客户端代码如下:

public class Client {

    public static void main(String[] args) throws Exception{
int rport=9528;
int sport=9527; DatagramChannel receiveChannel=DatagramChannel.open();
receiveChannel.configureBlocking(false);
DatagramSocket socket=receiveChannel.socket();
socket.bind(new InetSocketAddress(rport));
Selector selector=Selector.open();
receiveChannel.register(selector, SelectionKey.OP_READ); DatagramChannel sendChannel=DatagramChannel.open();
sendChannel.configureBlocking(false);
SocketAddress target=new InetSocketAddress("127.0.0.1",sport);
sendChannel.connect(target); BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in)); while(true){
String command=systemIn.readLine();
sendChannel.write(Charset.forName("UTF-8").encode(command));
if(command==null || "quit".equalsIgnoreCase(command.trim())){
systemIn.close();
sendChannel.close();
selector.close();
System.out.println("Client quit!");
System.exit(0);
}
int nKeys=selector.select(1000);
if(nKeys>0){
for (SelectionKey key : selector.selectedKeys()) {
if(key.isReadable()){
ByteBuffer buffer=ByteBuffer.allocate(1024);
DatagramChannel dc=(DatagramChannel) key.channel();
dc.receive(buffer);
buffer.flip();
System.out.println(Charset.forName("UTF-8").decode(buffer).toString());
buffer = null;
}
}
selector.selectedKeys().clear();
}
}
} }

分布式架构从零开始========》【基于Java自身技术实现消息方式的系统间通信】的更多相关文章

  1. 基于java自身技术实现消息方式的系统间通信

    这篇博客基本照搬了分布式java应用基础与实践一书的内容 java自带的远程调用分两种一种是rmi,一种是webservice 我们先看rmi(remote method invoke)# 使用rmi ...

  2. 基于JAVA WEB技术旅游服务网站系统设计与实现网上程序代写

    基于JAVA WEB技术旅游服务网站系统设计与实现网上程序代写 专业程序代写服务(QQ:928900200) 随着社会的进步.服务行业的服务水平不断发展与提高,宾馆.酒店.旅游等服务行业的信息量和工作 ...

  3. 基于java开发的在线题库系统tamguo

    简介 探果网(简称tamguo)是基于java开发的在线题库系统,包括 在线访问 后台运营 会员中心 书籍中心 管理员账号:system 密码:123456 因为线上数据和测试数据没有做到隔离,作者已 ...

  4. 系统间通信——RPC架构设计

    架构设计:系统间通信(10)——RPC的基本概念 1.概述经过了详细的信息格式.网络IO模型的讲解,并且通过JAVA RMI的讲解进行了预热.从这篇文章开始我们将进入这个系列博文的另一个重点知识体系的 ...

  5. 系统间通信(5)——IO通信模型和JAVA实践 下篇

    7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持.重点说明了IO模型是由操作系统提供支持,且这三种IO模 ...

  6. 架构设计:系统间通信(20)——MQ:消息协议(下)

    (接上文<架构设计:系统间通信(19)--MQ:消息协议(上)>) 上篇文章中我们重点讨论了"协议"的重要性.并为各位读者介绍了Stomp协议和XMPP协议. 这两种协 ...

  7. 架构设计:系统间通信(34)——被神化的ESB(上)

    1.概述 从本篇文章开始,我们将花一到两篇的篇幅介绍ESB(企业服务总线)技术的基本概念,为读者们理清多个和ESB技术有关名词.我们还将在其中为读者阐述什么情况下应该使用ESB技术.接下来,为了加深读 ...

  8. 系统间通信(3)——IO通信模型和JAVA实践 上篇

    来源:http://blog.csdn.net/yinwenjie 1.全文提要 系统间通信本来是一个很大的概念,我们首先重通信模型开始讲解.在理解了四种通信模型的工作特点和区别后,对于我们后文介绍搭 ...

  9. Java多线程学习(五)线程间通信知识点补充

    系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...

随机推荐

  1. HD1847 Good Luck in CET-4 Everybody!(巴什博弈)

    巴什博弈: 一堆物品n个,最多取m个,最少取1个,最后取走的人获胜 分析:只要保证取玩最后剩m+1个,则必定胜利,所以构造m+1,只要n是 m+1的倍数,则先手必败,每次先手取玩,后手可取使得剩下的仍 ...

  2. POJ2676Sudoku(类似于八皇后)

    Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16444   Accepted: 8035   Special ...

  3. Spring学习8-Spring事务管理(AOP/声明式式事务管理)

    一.基础知识普及 声明式事务的事务属性: 一:传播行为 二:隔离级别 三:只读提示 四:事务超时间隔 五:异常:指定除去RuntimeException其他回滚异常.  传播行为: 所谓事务的传播行为 ...

  4. Java,PostgreSQL时间范围查询

    遇到一坑:对于如下代码 select * from order_mileagefuel where date > '2015-11-1' and date< '2015-11-5' 在Po ...

  5. JS实现打字机式字符输出效果

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  6. 解决在IE中返回JSON格式的数据时提示下载的问题

    如题,以ASP.NET MVC为例,解决办法如下: 控制器中: public JsonResult Test() { return Json(json, "text/html"); ...

  7. 为自己的git添加alias,命令缩写

    在多人协作开发时,一般用git来进行代码管理.git有一些命令如:git pull . git push等等,这些命令可以设置alias,也就是缩写.如:git pull 是 git pl, git ...

  8. detours安装和使用

    http://blog.csdn.net/evi10r/article/details/6659354 http://blog.csdn.net/donglinshengan/article/deta ...

  9. 《CMake实践》第三部分的示例代码的错误

    <CMake实践>的第三章,初试cmake - cmake的helloworld 中的 PROJECT (HELLO) SET(SRC_LIST main.c) MESSAGE(statu ...

  10. [Effective JavaScript 笔记] 第1章:让自己习惯javascript小结

    在这里整理一下,每条对应的提示 第1条:了解使用的js版本 确定应用程序支持的js的版本(浏览器也是应用程序噢) 确保使用的js特性是应用程序支持的(要不写了也运行不了) 总是在严格模式下编写和测试代 ...