佛山cms建站系统,网站域名转出,中国外发加工网官网,广东建设信息网行业服务版前段时间用bio方式#xff0c;也就是传统io实现了socket的长连接和心跳#xff0c;总觉着服务端开启多线程管理socket连接的方式过于消耗资源#xff0c;数据并发的情况下可能会影响到性能#xff0c;因此就尝试使用nio改进原来的代码。然而改进的过程却不像我起初设想的那…前段时间用bio方式也就是传统io实现了socket的长连接和心跳总觉着服务端开启多线程管理socket连接的方式过于消耗资源数据并发的情况下可能会影响到性能因此就尝试使用nio改进原来的代码。然而改进的过程却不像我起初设想的那般容易可以说一波三折原因主要是nio读写都是字节流LZ一开始依然通过ObjectOutputStream.writeObject直接向Socket服务端发送数据然而问题出现了每次从ByteBuffer解析出来字节流都不一样LZ使出浑身解数一个字节一个字节的读取啊问题没有了可是由于是长连接数据怎么解析啊查资料找大神最后一个网友说有可能是粘包和分包的问题一时晕菜LZ网络可是渣渣啊行吧恶补一番想了解的童鞋可以看看这个。http://blog.csdn.net/sunmenggmail/article/details/38952131实现原理就像很多协议那样自定义一套传输协议比如消息长度(int型4个字节)消息体的方式根据解析的消息长度定长解析消息内容虽然最后证明LZ的问题不是由于粘包和分包造成的但是LZ就这样歪打正着给实现了数据不正常的问题后来通过DataOutputStream和DataInputStream的方式也得到了解决。废话多了帖代码。服务端package com.feng.test.longconnection1;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingDeque;import org.apache.commons.lang.ArrayUtils;/**** author songfeng* version 1.0* since 2015-10-24* category com.feng.test.longconnection**/public class Server{private Map heatTimeMap new HashMap();public Server(int port){Selector selector null;ServerSocketChannel serverChannel null;try{//获取一个ServerSocket通道serverChannel ServerSocketChannel.open();serverChannel.configureBlocking(false);serverChannel.socket().bind(new InetSocketAddress(port));//获取通道管理器selector Selector.open();//将通道管理器与通道绑定并为该通道注册SelectionKey.OP_ACCEPT事件//只有当该事件到达时Selector.select()会返回否则一直阻塞。serverChannel.register(selector, SelectionKey.OP_ACCEPT);while (selector.select() 0){//选择注册过的io操作的事件Iterator it selector.selectedKeys().iterator();while (it.hasNext()){SelectionKey readyKey it.next();//删除已选key防止重复处理it.remove();if (readyKey.isAcceptable()){ServerSocketChannel serverSocketChannel (ServerSocketChannel) readyKey.channel();SocketChannel socketChannel serverSocketChannel.accept();socketChannel.configureBlocking(false);// 连接成功后注册接收服务器消息的事件socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);}else if(readyKey.isReadable()){SocketChannel socketChannel (SocketChannel)readyKey.channel();Object obj receiveData(socketChannel);String msg Server back:;if(obj instanceof String){String id obj.toString().split(,)[0];if(heatTimeMap.get(id) ! null System.currentTimeMillis() - heatTimeMap.get(id) 5000){socketChannel.socket().close();}else{heatTimeMap.put(id, System.currentTimeMillis());}long time System.currentTimeMillis();msg time \n;sendData(socketChannel, msg);}else if(obj instanceof Pojo){msg ((Pojo)obj).getName() \n;sendData(socketChannel, msg);}}}}}catch (Exception e){e.printStackTrace();}finally{try{selector.close();if(serverChannel ! null){serverChannel.close();}}catch (Exception e){e.printStackTrace();}}}private static Object receiveData(SocketChannel socketChannel){Object obj null;ByteArrayOutputStream baos new ByteArrayOutputStream();ByteBuffer intBuffer ByteBuffer.allocate(4);ByteBuffer objBuffer ByteBuffer.allocate(1024);int size 0;int sum 0;int objlen 0;byte[] bytes null;try{while((size socketChannel.read(intBuffer)) 0){intBuffer.flip();bytes new byte[size];intBuffer.get(bytes);baos.write(bytes);intBuffer.clear();if(bytes.length 4){objlen bytesToInt(bytes,0);}if(objlen 0){byte[] objByte new byte[0];while(sum ! objlen){size socketChannel.read(objBuffer);if(size 0){objBuffer.flip();bytes new byte[size];objBuffer.get(bytes,0,size);baos.write(bytes);objBuffer.clear();objByte ArrayUtils.addAll(objByte, bytes);sum bytes.length;}}obj ByteToObject(objByte);break;}}}catch (Exception e){e.printStackTrace();}finally{try{baos.close();}catch (Exception e){e.printStackTrace();}}return obj;}private static void sendData(SocketChannel socketChannel,Object obj){byte[] bytes ObjectToByte(obj);ByteBuffer buffer ByteBuffer.wrap(bytes);try{socketChannel.write(buffer);}catch (IOException e){e.printStackTrace();}}/*** byte数组中取int数值本方法适用于(低位在前高位在后)的顺序。** param ary* byte数组* param offset* 从数组的第offset位开始* return int数值*/public static int bytesToInt(byte[] ary, int offset) {int value;value (int) ((ary[offset]0xFF)| ((ary[offset1]8) 0xFF00)| ((ary[offset2]16) 0xFF0000)| ((ary[offset3]24) 0xFF000000));return value;}public static Object ByteToObject(byte[] bytes){Object obj null;try{// bytearray to objectByteArrayInputStream bi new ByteArrayInputStream(bytes);ObjectInputStream oi new ObjectInputStream(bi);obj oi.readObject();bi.close();oi.close();}catch (Exception e){//e.printStackTrace();}return obj;}public static byte[] ObjectToByte(Object obj){byte[] bytes null;try{// object to bytearrayByteArrayOutputStream bo new ByteArrayOutputStream();ObjectOutputStream oo new ObjectOutputStream(bo);oo.writeObject(obj);bytes bo.toByteArray();bo.close();oo.close();}catch (Exception e){e.printStackTrace();}return bytes;}public static void main(String[] args){Server server new Server(55555);}}客户端package com.feng.test.longconnection1;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.Socket;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.util.ArrayList;/**** author songfeng* version 1.0* since 2015-10-24* category com.feng.test.longconnection**/public class Client{private Socket socket;private String ip;private int port;private String id;DataOutputStream dos;DataInputStream dis;public Client(String ip, int port,String id){try{this.ip ip;this.port port;this.id id;this.socket new Socket(ip, port);//this.socket.setKeepAlive(true);dos new DataOutputStream(socket.getOutputStream());dis new DataInputStream(socket.getInputStream());new Thread(new heartThread()).start();new Thread(new MsgThread()).start();}catch (Exception e){e.printStackTrace();}}public void sendMsg(Object content){try{int len ObjectToByte(content).length;ByteBuffer dataLenBuf ByteBuffer.allocate(4);dataLenBuf.order(ByteOrder.LITTLE_ENDIAN);dataLenBuf.putInt(0, len);dos.write(dataLenBuf.array(), 0 , 4);dos.flush();dos.write(ObjectToByte(content));dos.flush();}catch (Exception e){e.printStackTrace();closeSocket();}}public void closeSocket(){try{socket.close();dos.close();dis.close();}catch (IOException e){e.printStackTrace();}}public static byte[] ObjectToByte(Object obj){byte[] bytes null;try{// object to bytearrayByteArrayOutputStream bo new ByteArrayOutputStream();ObjectOutputStream oo new ObjectOutputStream(bo);oo.writeObject(obj);bytes bo.toByteArray();bo.close();oo.close();}catch (Exception e){e.printStackTrace();}return bytes;}public static Object ByteToObject(byte[] bytes){Object obj null;try{// bytearray to objectByteArrayInputStream bi new ByteArrayInputStream(bytes);ObjectInputStream oi new ObjectInputStream(bi);obj oi.readObject();bi.close();oi.close();}catch (Exception e){e.printStackTrace();}return obj;}class heartThread implements Runnable{Overridepublic void run(){while(true){try{Thread.sleep(1000);long time System.currentTimeMillis();//System.out.println(client send: time);sendMsg(Client id , time);}catch (Exception e){e.printStackTrace();}}}}class MsgThread implements Runnable{Overridepublic void run(){int temp;while(true){try{if(socket.getInputStream().available() 0){byte[] bytes new byte[1024];int len 0;while((char)(temp dis.read()) ! \n){bytes[len](byte)temp;len;}System.out.println(ByteToObject(bytes));}}catch (Exception e){closeSocket();}}}}public static void main(String[] args){Client client1 new Client(127.0.0.1, 55555, 1);client1.sendMsg(new Pojo(songfeng, 26, new ArrayList()));try{Thread.sleep(500);}catch (InterruptedException e){e.printStackTrace();}Client client2 new Client(127.0.0.1, 55555, 2);}}数据类:package com.feng.test.longconnection1;import java.io.Serializable;import java.util.List;/**** author songfeng* version 1.0* since 2015-10-16* category com.feng.test.longconnection**/public class Pojo implements Serializable{/*** 序列化*/private static final long serialVersionUID -8868529619983791261L;private String name;private int age;private List likeThing;public Pojo(String name, int age, List likeThing){super();this.name name;this.age age;this.likeThing likeThing;}public String getName(){return name;}public void setName(String name){this.name name;}public int getAge(){return age;}public void setAge(int age){this.age age;}public List getLikeThing(){return likeThing;}public void setLikeThing(List likeThing){this.likeThing likeThing;}}