`
从百草园到三味书屋
  • 浏览: 52255 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

基于Mina同步通信中存在的BUG的一种解决方案

 
阅读更多
需求:
有一个命令序列,包含三个命令
  • 1.调整命令
  • 2.测量命令
  • 3.获取命令

每个命令,对应的服务端都可能会返回一个字符串。
现在的需求是:
step1.发送命令1,如果服务端没返回结果,重新发送,如果返回了,则执行step2
step2.发送命令2,如果服务端没返回结果,重新发送,如果返回了,则执行step3
step3.发送命令3,如果服务端没返回结果,重新发送,如果返回了,则执行step1

针对这个需求,我之前也在问答模块里提过问,但是没人回答,请看下面的:
http://www.iteye.com/problems/86196

现在通信框架是基于Mina2的,Mina其实提供了同步通信操作

 session.getConfig().setUseReadOperation(true);  


但是实际用起来,却发现无法达到同步效果。网上也有类似的疑问,具体表现为:如果发送一条命令后,在给定的超时时间内,无法获取服务端相应,则后续的通讯将阻塞。简单的说就是如果通讯一旦产生超时,则无法恢复通讯。
       
我搜了一下网上的资源,也有人提到过这个问题:

http://bochengwen.iteye.com/blog/982062

进一步搜索发现在Mina网站上,还有外国人提过这个问题,但是一直都是Open状态。
https://issues.apache.org/jira/browse/DIRMINA-777?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel
引用

  • Status: Open Open
  • Resolution: Unresolved
  • Fix Version/s: 2.0.5



我当时也参与了评论,但是用的是中文文字,后来管理员直接把我的评论屏蔽了,而且还说:
Emmanuel Lecharny 写道
Emmanuel Lecharny added a comment - 19/Jul/12 07:26
Please, *do not* add comments in a foreign language... (even if those are related to the problem, google translate is not that good in chinese...)

晕死啊,老外就是老外。

看样子是准备2.0.5这个版本中fixed掉。对于这个bug,网上有网友提出了临时解决方案

((AbstractIoSession) session).offerReadFuture(null);// 针对同步实现的bug  


其实这样做并不能达到效果,具体原因我不想多说。我目前的解决方法是

String request = "XXXX"; 
					
/**发送数据到服务端**/

session.write(IoBuffer.wrap(request.getBytes()));  
/**
 * 获取Client.class的锁定,进入wait set,等待
 * 直到在Decoder中获取到了服务端响应的数据,notify,或者超时
 */					
synchronized(Client.class){
        try {
		Client.class.wait(3000L);
	} catch (InterruptedException e) {
		Thread.currentThread().interrupt();
	}
}					
/**下面的代码就是接收到数据后或者wait超时后执行的**/
codes...


在Decoder类中
 @Override  
    public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)  
            throws Exception {  
    	synchronized (Client.class) {
			Client.class.notifyAll();//唤醒
		}
othercode...
    }  


具体的notify的时机,应该根据需求而定的,例如我只要监听服务端返回数据就notiry的话,直接写在这里就行了,如果说还要判断数据是正确的才能发送下一条命令,那么显然放在这里notify是不合适的。
附:串口通讯程序

package comm;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import javax.comm.CommPortIdentifier;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;


/**
 * java串口通讯
 *
 * @author  administrator
 * @since   comm 1.0.0
 * @created 2012-8-2
 */
public class Comm {
	private SerialPort sPort;

	private OutputStream os ;

	private Map<String,List<String>> commands;

	private Recieved rec;
	
	public Comm(){
		commands = new ConcurrentHashMap<String, List<String>>();
		List<String> command1 = new ArrayList<String>();
		//初始化commands...
	}

	public boolean init(){
		try{
			CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier("COM3");
			sPort = (SerialPort) portId.open("TPS", 1000);
			sPort.setOutputBufferSize(8);
			sPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
			rec = new Recieved(sPort);
			sPort.addEventListener(rec);
			sPort.notifyOnDataAvailable(true); 
			sPort.enableReceiveTimeout(1000);
			os = sPort.getOutputStream();
		}catch(Exception e){
			return false;
		}
		return true;


	}

	public void start(){
		Timer t = new Timer();
		t.schedule(new TimerTask(){
			@Override
			public void run() {
				final Iterator<Entry<String,List<String>>> it = commands.entrySet().iterator();
				while(it.hasNext()){
					Entry<String,List<String>> e = it.next();
					for(String s:e.getValue()){
						System.out.println(e.getKey()+","+s);
						try {
							os.write(s.getBytes());
						} catch (IOException e1) {
							e1.printStackTrace();
						}
						synchronized (Comm.class) {
							try {
								Comm.class.wait(15000);
							} catch (InterruptedException e1) {
								Thread.currentThread().interrupt();
							}
						}
					}
				}
			}
			
		}, 1000,2000);
		
	}

	public static void main(String[] args) {
		Comm c = new Comm();
		c.init();
		c.start();
	}
}

class Recieved  implements SerialPortEventListener {
	private InputStream is;
	private SerialPort sPort;
	private StringBuffer msg = new StringBuffer();
	public Recieved(SerialPort sPort){
		this.sPort = sPort;
	}
	
	@Override
	public void serialEvent(SerialPortEvent e) {
		try {
			is = sPort.getInputStream();
		} catch (IOException e2) {
			e2.printStackTrace();
		}
		
		if (e.getEventType()==SerialPortEvent.DATA_AVAILABLE) { 
			try {
				while(is.available() > 0){
					msg.append((char)is.read());
				}
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		
			if(msg.toString().startsWith("%R1P")&&msg.toString().endsWith("\r\n")){
				System.out.println("recieved:"+msg);
				msg = new StringBuffer("");
				synchronized (Comm.class){
					Comm.class.notifyAll();
				}
			}
			
		}  
		
	}
}
分享到:
评论
1 楼 scholers 2013-02-27  
这个方法也不错,有兴趣换工作不?

相关推荐

    mina双向通信已测试

    本项目提供了一个完整的Mina双向通信示例,允许客户端和服务端互相发送消息。该demo的核心功能是接收用户输入的字符串并进行传输,适用于学习和理解Mina框架的通信机制。 **Mina框架** Mina采用事件驱动模型和非...

    Mina+Socket通信

    总的来说,Mina与Socket结合使用,可以构建出高效、灵活的网络通信解决方案。Mina的高级抽象简化了网络编程的复杂性,而Socket则提供了基础的网络通信能力。理解这两者的原理和用法,对于提升Java网络编程技能至关...

    一种基于Mina状态机的高性能服务器的设计方法

    基于 Mina 状态机的服务器设计方法是一种高效的服务器设计方法,能够提高服务器的性能和可靠性,降低软件开发的难度。该方法适用于开发高性能和高可靠性的网络应用程序,并且有广泛的应用前景。

    服务端基于MINA2的UDP双向通信Demo演示(MINA2服务端)

    “服务端基于MINA2的UDP双向通信Demo演示(MINA2服务端)” 这个标题表明这是一个使用MINA2框架在服务端实现的UDP(User Datagram Protocol)双向通信的示例代码。MINA2是一个开源的Java网络应用程序框架,它简化了...

    基于mina的及时通信

    Apache Mina是一个开源的网络通信框架,它为开发者提供了构建高性能、高可用性的网络应用程序的基础。本教程将带你走进基于Mina的即时通讯系统开发,适合初学者学习和实践。 **Apache Mina核心概念** Apache Mina...

    mina简单通信需要的包

    标题中的“mina简单通信需要的包”指的是Apache Mina框架,这是一个用于构建高性能、异步网络应用程序的Java框架。在本文中,我们将深入探讨Mina的核心概念和它在通信中的应用,以及与之相关的库SLF4J。 Apache ...

    mina 同步客户端,异步客户端

    mina是一个开源的Java框架,主要用于构建高性能、高可用性的网络通信应用。它的全名是Apache MINA (Multipurpose Infrastructure for Network Applications),它提供了一个抽象层,简化了开发复杂且高效网络服务的...

    在Java中运用mina来实现TCP通信

    这是一个有关Mina在Java通信中运用的简单的入门实例,MIna自带一种触发机制,无需再开线程等待收发数据。这个实例中有客户端和服务端,与软件TCPUDPDbg进行文字通话测试。用的时候注意添加Mina包,此实例中用到的是...

    基于 MINA 的 TLS/SSL NIO Socket 实现(二)

    在本篇博文中,我们将深入探讨如何利用Apache MINA库实现基于TLS/SSL的NIO(非阻塞I/O)Socket通信。MINA是一个高度可扩展的网络应用框架,广泛用于构建高性能、高并发的网络应用程序,如服务器端的TCP和UDP服务。...

    mina双向通信demo

    自己写的demo,完成了mina的双向通信功能,比较简单的一个demo,扩展性强

    服务端基于MINA2的UDP双向通信Demo演示(Java客户端)

    标题中的“服务端基于MINA2的UDP双向通信Demo演示(Java客户端)”是指使用Apache MINA框架在Java中实现的UDP(用户数据报协议)的双向通信示例。MINA是一个高性能、异步的网络应用程序框架,常用于构建网络服务,如...

    Mina网络通信传输

    Mina网络通信传输是基于Java开发的一个高性能、可伸缩的网络应用框架,常用于构建服务器和客户端之间的通信系统,尤其适用于即时聊天应用。Mina提供了丰富的API和工具,简化了网络编程的复杂性,使得开发者可以专注...

    Android-MinaSocket一款基于Mina的Socket长连接库

    `Android-MinaSocket` 是一个针对Android平台的长连接库,它基于Apache Mina框架,提供了稳定且高效的网络通信能力。 Apache Mina(Model-View-Controller for Network Applications)是一个高度可扩展和灵活的网络...

    基于spring的Mina框架

    总的来说,基于Spring的Mina框架结合了Spring的灵活性和Mina的高性能,为企业级的网络通信服务提供了强大的解决方案。开发者可以通过熟练掌握这两个框架的整合,构建出稳定、可扩展的网络应用。

    XMPP与MINA

    XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通信协议,广泛应用于即时通讯、VoIP、协作软件等场景。它提供了丰富的扩展机制,允许开发者添加自定义功能。而MINA(Multipurpose ...

    基于MINA2实现的UDP双向通信源码

    本源码是《NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战》一文的服务端实现(MINA2版),详见:http://www.52im.net/thread-378-1-1.html

    Mina通信框架应用示例

    Mina通信框架,全称为Apache MINA,是一个高度可扩展的、基于Java的网络应用程序开发框架。MINA的名字来源于多语言(Multi-purpose Infrastructure for Network Applications),它提供了非阻塞I/O(Non-blocking I/...

    mina网络通信实例

    在实际应用中,创建一个MINA网络通信实例通常包括以下步骤: 1. **选择合适的Transport类型**:MINA提供了多种传输层实现,如Socket Transport用于TCP协议,Datagram Protocol用于UDP协议。 2. **配置Acceptor**:...

    MinaServer for Android

    总的来说,MinaServer为Android开发者提供了一种在移动设备上搭建服务端应用的解决方案,利用Apache Mina的强大功能,可以轻松处理网络通信任务。对于希望扩展Android应用功能或构建分布式系统的开发者来说,这是一...

    jbpm4.3 流程申请(mina通信)

    在这个例子中,我们关注的是如何在jbpm4.3中实现基于Mina的服务端和客户端通信。 **Mina通信框架** Apache Mina是一个高性能、轻量级的网络通信框架,用于构建网络应用,如TCP/IP和UDP协议的应用。它提供了异步...

Global site tag (gtag.js) - Google Analytics