锁定老帖子 主题:网站系统中应用mina
精华帖 (0) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (7)
|
|
---|---|
作者 | 正文 |
发表时间:2010-02-26
lzp0070007 写道 sundoctor 写道 引用 在这里遇到了问题,接收后的数据该如何返回给客户端(浏览器端)
这个问题其实很简单,没有大家想的那么复杂,只是大家没有想到点子上而己,解决办法就是要将接收后的数据和当前请求联系起来就可以返回给客户端了,以下是简单的解决办法: 在车务通系统客户端,也就是浏览器页面,发出请求,调用mina客户端的Iosession.write()方法,发送请求前产生一个系统全局唯一标识,并将这个标识保存到Iosession中,如: /** * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse * response) */ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String param1 = request.getParameter("param1"); // 创建客户端连接器 IoConnector connector = new NioSocketConnector(); // 设置事件处理器 connector.setHandler(new ClientHandler()); // 设置编码过滤器和按行读取数据模式 connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); // 创建连接 ConnectFuture future = connector.connect(new InetSocketAddress(TARGET_IP, PORT)); // 等待连接创建完成 future.awaitUninterruptibly(); // 获取连接会话 IoSession session = future.getSession(); // 产生当次发送请求标识,标识由客户端地址+随机数 // 这里的标识只是一个例子,标识可以任何方法产生,只要保持在系统中的唯一性 String flag = request.getLocalAddr() + UUID.randomUUID().toString(); //将标识保存到当前session中 session.setAttribute("SendRequestFlag", flag); /// 发送信息 session.write(param1); /// 等待连接断开 session.getCloseFuture().awaitUninterruptibly(); connector.dispose(); //通过标识获取保存的结果 Object result = ClientHandler.results.get(flag); //清除标识内容 ClientHandler.results.remove(flag); //将结果返回客户端 response.getWriter().write(result.toString()); } 然后在mina客户端(车务通系统中接收),messageReceive()方责接收到消息时将系统全局唯一标识从Iosession中取出,将其和当前数据绑定保存,如: public static final Map<String,Object> results = new ConcurrentHashMap<String,Object>(); public void messageReceived(IoSession session, Object message) throws Exception { //从session中取到标识 String flag = (String)session.getAttribute("SendRequestFlag"); //将从服务端接收到的message和标识绑定保存,可以保存到内存、队列、文件、数据库等等 //在这里简单的以标识为key,message为value保存到Map中 results.put(flag, message); //关闭session session.close(true); } 最后通过系统全局唯一标识获取结果并返回给客户端 //通过标识获取保存的结果 Object result = ClientHandler.results.get(flag); //清除标识内容 ClientHandler.results.remove(flag); //将结果返回客户端 response.getWriter().write(result.toString()); 用servlet简单写了一个例子,以供参考,见附件。采用同步、异步调用均可,任君选择,在这例子中我采用jquery的ajax异步调用 你写的代码基本可以满足我的需求,不过有个问题,如果我只想建立一个连接来完成所有操作,而不是每次都新建连接,这个能实现吗?在你原有代码的基础上如何改动?谢谢 一个iosession就是表示一个连接,如果你一个连接要完成所有操作,哪意味着你的每一个ie请求标识要放到session.write(param1)中,并且在接收消息的时候通过这个标识去唤醒对应的ie请求线程,这个实现起来没多大意义!当然如果是一次ie中有多次请求,应该是可以的,只要session.close(true)前判断当前的操作是否都已返回了,再关闭连接就行了! |
|
返回顶楼 | |
发表时间:2010-02-27
一般这类问题需要发散开来考虑
如果一个通信协议中request/response没有定义任何匹配标志,那么一般应用交互场景只有两种可能: 1. 按时序区分,串行的协议,即client发出请求后收到响应才能发出第二个请求,server端亦然; 2. 按连接区分,即一个request/response在单独的connection中完成,不能与其它的request/response对重复 |
|
返回顶楼 | |
发表时间:2010-02-28
直接传递到浏览器吗?可以先传递给调用这个接口的服务端啊(相对的客户端),然后再有服务端展现给浏览器
|
|
返回顶楼 | |
发表时间:2010-03-01
最后修改:2010-03-01
说下我的解决办法:为每个用户提供个连接,保存在session中,后面采用了sundoctor 的意见,不过修改了触发时机,
session.write(str.toString()); session.read().awaitUninterruptibly(); Object result = ClientHandler.results.get(flag); ClientHandler.results.remove(flag); public synchronized void messageReceived(IoSession session, Object message) throws Exception { String flag = (String)session.getAttribute("SendRequestFlag"); results.put(flag, message); //session.close(true); } 大家可以继续讨论 |
|
返回顶楼 | |
发表时间:2010-03-01
每个用户一个连接,当用户量大到一定程度,你的mina服务器就不行了。
|
|
返回顶楼 | |
发表时间:2010-03-01
sundoctor 写道 引用 你写的代码基本可以满足我的需求,不过有个问题,如果我只想建立一个连接来完成所有操作,而不是每次都新建连接,这个能实现吗?在你原有代码的基础上如何改动?谢谢
我写的只是一个简单的代码,以供参考,给你提示一下思路而己,你得根据你的项目使用情况进行修改。建立一个连接来完成所有操作可以实现。 说下我的解决办法:为每个用户提供个连接,保存在session中,后面采用了sundoctor 的意见,不过修改了触发时机, session.write(str.toString()); session.read().awaitUninterruptibly(); Object result = ClientHandler.results.get(flag); ClientHandler.results.remove(flag); public void messageReceived(IoSession session, Object message) throws Exception { String flag = (String)session.getAttribute("SendRequestFlag"); results.put(flag, message); //session.close(true); } 不过还有问题 ,有时候这种触发方式 会失效,不等messageReceieve()返回 就执行下面的代码,结果得到为空的对象, 请问这是怎么回事 |
|
返回顶楼 | |
发表时间:2010-03-02
lzp0070007 写道 sundoctor 写道 引用 你写的代码基本可以满足我的需求,不过有个问题,如果我只想建立一个连接来完成所有操作,而不是每次都新建连接,这个能实现吗?在你原有代码的基础上如何改动?谢谢
我写的只是一个简单的代码,以供参考,给你提示一下思路而己,你得根据你的项目使用情况进行修改。建立一个连接来完成所有操作可以实现。 说下我的解决办法:为每个用户提供个连接,保存在session中,后面采用了sundoctor 的意见,不过修改了触发时机, session.write(str.toString()); session.read().awaitUninterruptibly(); Object result = ClientHandler.results.get(flag); ClientHandler.results.remove(flag); public void messageReceived(IoSession session, Object message) throws Exception { String flag = (String)session.getAttribute("SendRequestFlag"); results.put(flag, message); //session.close(true); } 不过还有问题 ,有时候这种触发方式 会失效,不等messageReceieve()返回 就执行下面的代码,结果得到为空的对象, 请问这是怎么回事 你向浏览器写数据的时候你能确定你已经messageReceived了?你已经要确定messageReceived要在你向浏览器写数据之前 |
|
返回顶楼 | |
发表时间:2010-03-16
leixm 写道 这是一个监听的例子: future.addListener(new IoFutureListener<ConnectFuture>() { public void operationComplete(ConnectFuture future) { IoSession session = future.getSession(); while (!session.isClosing()) { try { Thread.sleep(100); String result=(String) session.getAttribute("resp"); if(result!=null){ System.out.println("传过来的值是:"+result); session.removeAttribute("resp"); } } catch (InterruptedException e) { e.printStackTrace(); } } } }); 请问 你写的这个监听,是在什么时候触发,是当连接关闭时,还是当收到信息就会触发, 我想要写个在收到信息就会触发的监听 |
|
返回顶楼 | |
发表时间:2010-12-21
sundoctor 写道 引用 在这里遇到了问题,接收后的数据该如何返回给客户端(浏览器端)
这个问题其实很简单,没有大家想的那么复杂,只是大家没有想到点子上而己,解决办法就是要将接收后的数据和当前请求联系起来就可以返回给客户端了,以下是简单的解决办法: 在车务通系统客户端,也就是浏览器页面,发出请求,调用mina客户端的Iosession.write()方法,发送请求前产生一个系统全局唯一标识,并将这个标识保存到Iosession中,如: /** * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse * response) */ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String param1 = request.getParameter("param1"); // 创建客户端连接器 IoConnector connector = new NioSocketConnector(); // 设置事件处理器 connector.setHandler(new ClientHandler()); // 设置编码过滤器和按行读取数据模式 connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); // 创建连接 ConnectFuture future = connector.connect(new InetSocketAddress(TARGET_IP, PORT)); // 等待连接创建完成 future.awaitUninterruptibly(); // 获取连接会话 IoSession session = future.getSession(); // 产生当次发送请求标识,标识由客户端地址+随机数 // 这里的标识只是一个例子,标识可以任何方法产生,只要保持在系统中的唯一性 String flag = request.getLocalAddr() + UUID.randomUUID().toString(); //将标识保存到当前session中 session.setAttribute("SendRequestFlag", flag); /// 发送信息 session.write(param1); /// 等待连接断开 session.getCloseFuture().awaitUninterruptibly(); connector.dispose(); //通过标识获取保存的结果 Object result = ClientHandler.results.get(flag); //清除标识内容 ClientHandler.results.remove(flag); //将结果返回客户端 response.getWriter().write(result.toString()); } 然后在mina客户端(车务通系统中接收),messageReceive()方责接收到消息时将系统全局唯一标识从Iosession中取出,将其和当前数据绑定保存,如: public static final Map<String,Object> results = new ConcurrentHashMap<String,Object>(); public void messageReceived(IoSession session, Object message) throws Exception { //从session中取到标识 String flag = (String)session.getAttribute("SendRequestFlag"); //将从服务端接收到的message和标识绑定保存,可以保存到内存、队列、文件、数据库等等 //在这里简单的以标识为key,message为value保存到Map中 results.put(flag, message); //关闭session session.close(true); } 最后通过系统全局唯一标识获取结果并返回给客户端 //通过标识获取保存的结果 Object result = ClientHandler.results.get(flag); //清除标识内容 ClientHandler.results.remove(flag); //将结果返回客户端 response.getWriter().write(result.toString()); 从上可知,我们可以通过IoSession将一个标识传到messageReceived方法中,熟悉web开发的知道,IoSession在这里跟HttpSession使用方式一样,因此我们可以将任何东东通过IoSession传到messageReceived方法中,比如HttpServletRequest、HttpServletResponse、Spring bean、Hibernate Dao、数据库连接等等。反之,在messageReceived方法中通过IoSession将接收后的数据或任何其它东东传到外面,这时就不能在messageReceived方法中关闭IoSession了。 用servlet简单写了一个例子,以供参考,见附件。采用同步、异步调用均可,任君选择,在这例子中我采用jquery的ajax异步调用 如果共用session呢? |
|
返回顶楼 | |
发表时间:2010-12-25
顶帖 我也急求知道这个问题的解决方案!
|
|
返回顶楼 | |