采用list传输格式的webservice实现控制远程设备
? 前些天在弄一个远程指令控制传感设备的程序,大体思路是这样的:用webservice作为中间服务程序,各平台作为客户端。客户端点击开启按钮调用webservice,webservice向传感设备发送开启指令,webservice和设备之间为TCP连接,分别为socketcliet和socketserver。二者会保持10秒的连接时间,传感设备数据会保存在webservice数据库中,10秒之后把数据封装成list传给平台客户端。如下图所示:
相关技术: ? ??webService:axis2框架,该框架相关部署不在赘述了 ? ? 数据库:mysql数据库 ? ? 采用线程池和NIO保证数据非阻塞 ? ? ? ? ? ? ??当平台发送一条指令时会开启一个线程,该线程作为socket客户端与传感设备的路由(socketserver端)进行通信。线程都通过线程池进行管理,当与设备通信超时后(这里为10秒)会关闭该线程 重新放回池中。 ? ? ? ? ? 为防止socketclient端阻塞,socket采用NIO流进行传输,以防止阻塞的发生。 ? ? ? ? ? webservice向平台返回数据采用list方式,将查询结果封装成model对象 再将model放到list,采用这种方式更利于表结构数据传输而且提高传输效率。下面是平台调用webservice的代码: public class test { public static void main(String[] args) throws Exception{ List<HashMap<String,Object>> returns = new ArrayList<HashMap<String,Object>>(); RPCServiceClient serviceClient = new RPCServiceClient(); Options options = serviceClient.getOptions(); EndpointReference targetEPR = new EndpointReference("http://192.168.1.100:8080/XML/services/HelloWorld"); options.setTo(targetEPR); QName opAddEntry = new QName("http://jdbc.mysql.com","getList2"); Object[] so = serviceClient.invokeBlocking(opAddEntry,new Object[] {"美女"},new Class[] {Object[].class }); if (so.length > 0) { if (so[0] instanceof Object[]) { Object[] elements = (Object[]) so[0]; for (Object o : elements) { HashMap<String,Object> maps = new HashMap<String,Object>(); OMElementImpl ome = (OMElementImpl) o; maps.put(ome.getLocalName(),ome.getText()); while (ome.getNextOMSibling() != null) { ome = (OMElementImpl) ome.getNextOMSibling(); maps.put(ome.getLocalName(),ome.getText()); } returns.add(maps); } } else { Object ob = so[0]; if (ob instanceof OMElementImpl == false) { HashMap<String,Object>(); maps.put("simple",ob); returns.add(maps); } else { OMElementImpl ome = (OMElementImpl) so[0]; HashMap<String,Object>(); maps.put(ome.getLocalName(),ome.getText()); returns.add(maps); } } println(returns); } else { println(returns);; } } public static void println(List<HashMap<String,Object>> list) { for (HashMap<String,Object> maps : list) { System.out.println("------------------"); Set<String> set = maps.keySet(); Iterator<String> it = set.iterator(); while (it.hasNext()) { String key = it.next(); Object value = maps.get(key); System.out.print(key + ":" + value + "t"); } System.out.println(); } } } 客户端所用jar包:http://download.csdn.net/detail/kakarottoz/8136915 webservice服务端方法如下:
public List<Model> getList2(String mac) throws Exception{ List<Model> list = new ArrayList<Model>(); if(connect(1,mac)){ String sql="相应的sql"; Connection con = getConn(); Statement sta = con.createStatement(); ResultSet rs = sta.executeQuery(sql); while(rs.next()){ Model m = new Model(); m.setTfShuL(rs.getInt("tfShuL")); m.setTfMingC(rs.getString("tfMingC")); m.setTfGuiG(rs.getString("tfGuiG")); m.setTfPinM(rs.getString("tfPinM")); m.setTfDaL(rs.getString("tfDaL")); m.setTfZhuDW(rs.getString("tfZhuDW")); list.add(m); } } return list; } ? 开启线程的connect方法如下:
public boolean connect(int machid,String mac) throws Exception{ try{ oz oz = new oz(); oz.initClient("192.168.1.110",8899,machid,mac); Thread td = new Thread(oz); pool.submit(td); //线程池 Thread.sleep(8000); }catch(Exception e){ System.out.println(e.getLocalizedMessage()); return false; } return true; } ?oz是一个自己实现的线程对象,里面也实现了一个NIO的socket客户端,可与传感设备组成的网络进行通信。代码如下:
public class oz implements Runnable { private final static byte[] hex = "0123456789ABCDEF".getBytes(); private Selector selector; Statement sta; ByteBuffer buffer = ByteBuffer.allocate(21); private byte[] command=null; private static String mac; public void initClient(String ip,int port,int machid,String mac) throws Exception { command=new byte[11]; command[0]=(byte)0xA0; command[1]=0x00; command[2]=0x04; command[3]=0x00; command[4]=0x00; command[5]=0x00; command[6]=0x00; command[7]=0x01; command[8]=(byte)0xA0; command[9]=0x04; command[10]=(byte)0xB7; Connection con = getConn(); sta = con.createStatement(); // 获得一个Socket通道orz this.mac=mac; SocketChannel channel = SocketChannel.open(); // 设置通道为非阻塞 channel.configureBlocking(false); // 获得一个通道管理器 this.selector = Selector.open(); // 客户端连接服务器,其实方法执行并没有实现连接,需要在listen()方法中调 // 用channel.finishConnect();才能完成连接 channel.connect(new InetSocketAddress(ip,port)); // 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT事件。 channel.register(selector,SelectionKey.OP_CONNECT); } /** * 处理读取服务端发来的信息 的事件 * @param key * @throws IOException */ public void read(SelectionKey key) throws IOException { // 和服务端的read方法一样 SocketChannel channel = (SocketChannel) key.channel(); // 创建读取的缓冲区 ByteBuffer buffer = ByteBuffer.allocate(14); channel.read(buffer); byte[] data = buffer.array(); // String msg = new String(data).trim(); String msg = Bytes2HexString(data); System.out.println("服务端收到信息:"+msg); try { insert(msg,sta); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ channel.close(); } // ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes()); } /** * author: * time:2014-10-14 * @param rfid rfid号 * @param sta 数据集合对象 * @return * @throws Exception */ public int insert(String rfid,Statement sta) throws Exception{ int n=0; //int boo = sta.executeUpdate("delete from statistics"); System.out.println(rfid); String sql="insert into realrfid(rfid,realtime,mac) values('"+rfid.substring(4,28)+"',NOW(),'2','"+mac+"') "; System.out.println(sql); n = sta.executeUpdate(sql); return n; } public void run() { // TODO Auto-generated method stub while (true) { try { int keys = selector.select(10000); if (keys == 0) { System.out.println("链接已经结束"); break; } // 获得selector中选中的项的迭代器 Iterator ite = this.selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey key = (SelectionKey) ite.next(); // 删除已选的key,以防重复处理 ite.remove(); // 连接事件发生 if (key.isConnectable()) { SocketChannel channel = (SocketChannel) key.channel(); // 如果正在连接,则完成连接 if (channel.isConnectionPending()) { channel.finishConnect(); channel.register(this.selector,SelectionKey.OP_READ); } // 设置成非阻塞 channel.configureBlocking(false); // 在这里可以给服务端发送信息哦 channel.write(ByteBuffer.wrap(command)); // 在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。 // 获得了可读的事件 } else if (key.isReadable()) { // SocketChannel channel = (SocketChannel) // key.channel(); // channel.read(buffer); // byte[] data = buffer.array(); // String rfid = Bytes2HexString(data); // insert(rfid,sta); read(key); } } } catch (Exception e) { System.out.println(e.getLocalizedMessage()); } } } public static String Bytes2HexString(byte[] b) { byte[] buff = new byte[2 * b.length]; for (int i = 0; i < b.length; i++) { buff[2 * i] = hex[(b[i] >> 4) & 0x0f]; buff[2 * i + 1] = hex[b[i] & 0x0f]; } return new String(buff); } private static Connection getConn() throws Exception { Connection conn=null; String type= "mysql"; if(type=="mysql" ){ Class. forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(""); } else if ("sqlserver" .equals(type)){ Class. forName("net.sourceforge.jtds.jdbc.Driver"); } return conn; } } ? ? ? ? ?以上就是一个简单地通过webservice实现平台和硬件设备的通信实例,使用webservice可以适应多种平台 便于更新扩展同时便于数据的集中处理,其他好处想必大家日后会慢慢发现。。NIO可防止阻塞提高传输效率。 ? ? ? ? 还有很多问题有待解决,比如数据的排队问题、线程和socket的优化等等。欢迎大家多多指正 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |