基于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. myeclipse 部署应用

    昨天把MyEclipse10给安装上了,今天想在MyEclipse下启动Tomcat并在浏览器中看到写的Web页面,但是当在浏览器中输入地址时,出现了404错误,出现这个错误的原因是因为没有找到指定的 ...

  2. JSP业务逻辑层

    经典的三层架构:表示层.业务逻辑层和数据访问层 具体的区分方法 1:数据访问层:主要看你的数据层里面有没有包含逻辑处理,实际上他的各个函数主要完成各个对数据文件的操作.而不必管其他操作. 2:业务逻辑 ...

  3. Beta版本——冲刺计划及安排

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  4. POJ3041Asteroids(最小点覆盖+有点小抽象)

    Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18289   Accepted: 9968 Descri ...

  5. SQL localdb 连接字符串

    http://blog.csdn.net/greystar/article/details/47699797 原来SQL 2012 下连接LOCALDB,字符串为: Data Source=(Loca ...

  6. Shell编程检测监控mysql的CPU占用率

    shell编程很强大! 网站访问量大的时候mysql的压力就比较大,当mysql的CPU利用率超过300%的时候就不能提供服务了,近乎卡死状态,这时候最好的方法就是重启mysql服务.由于这种事具有不 ...

  7. mysql union 详解

    Union:作用:把2次或多次查询结果合并起来要求:两次查询的列数一致推荐:查询的每一列,相对应的列类型也一样 可以来自于多张表 多次sql语句取出的列名可以不一致,此时,以第1个sql的列名为准 例 ...

  8. DataGridView设置不自动显示数据库中未绑定的列

    项目中将从数据库查出来的数据绑定到DataGridView,但是不想显示所有的字段.此功能可以通过sql语句控制查出来的字段数目,但是DataGridView有属性可以控制不显示未绑定的数据,从UI层 ...

  9. 自定义 SqlHelp

    using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Data; usin ...

  10. ajax 之js读取xml的多浏览器兼容

    主要是分为两大类:IE.其它浏览器 IE8以下只支持这种 InputVoltage.innerText = xmlDoc.getElementsByTagName(id)[0].text, 其它浏览器 ...