java socket 持久 对比_java socket IO和NIO的对比

先上一个最基本的socket io的例子,首先是server端:

ServerSocket serverSocket = new ServerSocket(PORT);

while (true) {

Socket client = serverSocket.accept();

new HandlerThread(client);

}

DataInputStream input = new DataInputStream(socket.getInputStream());

DataOutputStream out = new DataOutputStream(socket.getOutputStream());

while(true){

String clientInputStr = input.readUTF();

}

首先new一个ServerSocket,之后循环监听,得到一个新的连接之后,交给一个HandlerThread来处理。

而在HandlerThread当中,也是需要阻塞的方式来读取输入,读不着了就等着。

然后是client端:

socket = new Socket(IP_ADDR, PORT);

DataInputStream input = new DataInputStream(socket.getInputStream());

DataOutputStream out = new DataOutputStream(socket.getOutputStream());

while(true){

String str = new BufferedReader(new InputStreamReader(System.in)).readLine();

out.writeUTF(str);

String ret = input.readUTF();

}

而在client当中,大同小异,new一个socket对象,连接到server上,之后向server发信息,然后等着server的响应。

上面3处标红的地方,server监听接入,server和client的读取input stream,都是通过阻塞的方式来完成。如果说,一个server介入了若干个连接,就需要若干个线程来完成和客户端的通信工作。

然后我们再上一个java nio的例子,首先是server端:

ServerSocketChannel serverChannel = ServerSocketChannel.open();

serverChannel.configureBlocking(false);

serverChannel.socket().bind(new InetSocketAddress(port));

this.selector = Selector.open();

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

public void listen() throws Exception {

while (true) {

selector.select();

Iterator ite = this.selector.selectedKeys().iterator();

while (ite.hasNext()) {

SelectionKey key = (SelectionKey) ite.next();

ite.remove();

if (key.isAcceptable()) {

ServerSocketChannel server = (ServerSocketChannel) key.channel();

SocketChannel channel = server.accept();

channel.configureBlocking(false);

channel.write(ByteBuffer.wrap(new String("hello client").getBytes()));

channel.register(this.selector, SelectionKey.OP_READ);

} else if (key.isReadable()) {

read(key);

}

}

}

}

private void read(SelectionKey key) throws Exception {

SocketChannel channel = (SocketChannel) key.channel();

ByteBuffer buffer = ByteBuffer.allocate(10);

channel.read(buffer);

byte[] data = buffer.array();

String msg = new String(data).trim();

System.out.println("server receive from client: " + msg);

ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());

channel.write(outBuffer);

}

基本流程解释一下:

首先是准备阶段,生成一个server channel的对象,然后绑定端口,再打开一个selector,注册accept事件。

然后是监听,监听到一个连接,accept,并返回一个socket channel,把这个客户端channel的read事件注册到selector,注意,这里的selector跟之前监听server channel的是同一个,也就是说,目前这个selector要听2件事,一个是监听室针对server channel,另一个是监听client channel有没有数据进来。

有数据进来的话,读数据,然后写个返回回去。

然后是client端:

SocketChannel channel = SocketChannel.open();

channel.configureBlocking(false);

this.selector = Selector.open();

channel.connect(new InetSocketAddress(ip, port));

channel.register(selector, SelectionKey.OP_CONNECT);

public void listen() throws Exception { // 轮询访问selector

while (true) {

selector.select(); // 获得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.configureBlocking(false);

channel.write(ByteBuffer.wrap(new String("hello server!").getBytes()));

channel.register(this.selector, SelectionKey.OP_READ); // 获得了可读的事件

} else if (key.isReadable()) {

read(key);

}

}

}

}

private void read(SelectionKey key) throws Exception {

SocketChannel channel = (SocketChannel) key.channel();

ByteBuffer buffer = ByteBuffer.allocate(10);

channel.read(buffer);

byte[] data = buffer.array();

String msg = new String(data).trim();

System.out.println("client receive msg from server:" + msg);

ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());

channel.write(outBuffer);

}

这里也需要简单解释一下流程:

准备阶段,创建一个SocketChannel对象,连接到服务器上,然后打开一个selector,注册connect事件到selector上。

然后同样是监听,监听到服务器已经响应了自己的连接,需要调用一个finishConnect方法,这就算是完成连接了,把read事件注册到selector上。

读到服务器响应,读取数据,返回响应。

到此为止,对于io和nio的实现方式,我们都已经有了大体的了解,我们现在来比较一下2种方式的不同点:

1、多路选择器(selector)的使用,使得一个线程可以针对多个channel进行监听,大大的减少线程的数量,提高了系统运行的效率。

2、io是针对流的,而nio针对的是缓冲区,而在缓冲区当中指针可以任意进行移动,对某些复杂的业务场景,可以极大地简化编程的复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值