JavaSE中基于Socket的网络通信是阻塞式的,当程序执行输入输出操作后,在这些操作返回之前会一直阻塞该线程,使得服务器要为每一个客户端提供线程进行数据处理,这种处理不适合处理数量多的客户端,jdk1.4后Java引入了nio.
在进行网络编程时,使用SocketChannel大大减轻了服务器的负担,在此贴上如何讲一个对象装入ByteBuffer的:
数据包解析(部分代码):
在进行网络编程时,使用SocketChannel大大减轻了服务器的负担,在此贴上如何讲一个对象装入ByteBuffer的:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
public class BStream {
public static ByteBuffer toByteBuffer(Object object) {
ByteArrayOutputStream bio = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
ByteBuffer outBuf = null;
try {
//包装字节流
oos = new ObjectOutputStream(bio);
//将对象写入字节流
oos.writeObject(object);
//得到对象字节
byte[] ba = bio.toByteArray();
//得到对象字节的长度
int len = ba.length;
//字节缓冲区的大小为INT + 对象字节的长度
outBuf = ByteBuffer.allocate((Integer.SIZE >> 3) + len);
//压入数据:数据长度
outBuf.putInt(len);
//压入数据:对象数据
outBuf.put(ba);
//归位
outBuf.flip();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bio != null)
bio.close();
if (oos != null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return outBuf;
}
public static Object toObject(byte[] buff) {
ByteArrayInputStream bis = new ByteArrayInputStream(buff);
ObjectInputStream ois = null;
try {
//包装字节数组流
ois = new ObjectInputStream(bis);
} catch (IOException e) {
e.printStackTrace();
}
Object object = null;
try {
//读入对象
object = ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (bis != null)
bis.close();
if (ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return object;
}
}
数据包解析(部分代码):
System.out.println("client message");
//获取客户端通信的SocketChannel
SocketChannel sc = (SocketChannel) sk.channel();
// new ServiceThread(sc).start();
byte[] data = null;
try {
ByteBuffer lenbuff = ByteBuffer.allocate(4);
//读入对象数据的大小
sc.read(lenbuff);
lenbuff.flip();
int len = lenbuff.getInt();
if(len == 0) {
return;
}
//分配ByteBuffer的大小
ByteBuffer buff = ByteBuffer.allocate(len);
//一次性读取所有数据
sc.read(buff);
buff.flip();
data = buff.array();
sk.interestOps(SelectionKey.OP_READ);
} catch (IOException e) {
if(sk.channel() != null) {
sk.channel().close();
}
// e.printStackTrace();
}
//转成请求的对象
Request request = (Request) BStream.toObject(data);
String action = request.getAction();