java NIO socket编程简介
来源:互联网 发布:变性手术知乎 编辑:程序博客网 时间:2024/04/29 17:34
针对于BIO的弊端,在java后续版本中推出了NIO,在此之前,网络通信方面很少使用java的BIO,有更好的为何不用。N可以理解为new的意思,新的io,在NIO里面可以选择不阻塞,默认是阻塞的。NIO的三大 核心channel,buffer,selector,通道用于传输数据,类似于流,buffer存储数据的缓冲,selector选择器。对于它们的工作,我是这么认为的,channerl注册selector,channel可以注册读,写等多个,selector通过遍历里面的元素,获取数据,数据的都和 写通过buffer来实现,传输时通过channel,在遍历的时候,取出数据,或者存入数据,如果什么也没有或者什么也没有写入,那么就什么也没有,这样就可以实现一个线程控制多个socket。当然大型服务器是不可能只使用一个selector的,通常一个网段使用一个或者多个selector,所以说网络方面比较复杂,能够使用netty等框架,就不要自己去实现一个框架来实现自己的功能,当然大牛就是写框架的。用的少,不代表不要精通,这是通往大牛的一步,要带着理想学习。
客户端 仅是简单的发送
package com.wsdc.socket;import java.io.IOException;import java.net.InetSocketAddress;import java.net.SocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import java.util.concurrent.TimeUnit;public class Client { public static void main(String[] args) { SocketChannel sc = null; try { sc = SocketChannel.open(); sc.configureBlocking(false); sc.connect(new InetSocketAddress("127.0.0.1", 9999)); if(sc.finishConnect()){ ByteBuffer bb = ByteBuffer.allocate(1024); String str = "少年壮志不言愁"; while(true){ bb.clear(); TimeUnit.SECONDS.sleep(1); bb.put(str.getBytes()); bb.flip(); sc.write(bb); System.out.println("发送数据"); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
服务端 java对于通信的操作均是socket,无论采取那种方式,均是可以 读取数据的,也就是说,用BIO的方式发送,用NIO的方式接收,这是完全没有问题的,只不过是面向socket的不同方向而已,本质均是从 socket中读取和写入数据
package com.wsdc.socket;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.net.Socket;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.util.Iterator;import java.util.concurrent.TimeUnit;/** * * @author ASUS * 只要是socket通信 无论是使用io还是nio均可以使用 * * io或者nio来接收 实现混合使用 当然这里指的是服务端和客户端可以使用不同 * * 的策略 对于同一侧应该要使用同一种类型 * * 底层实现的是TCP/IP,无论是io还是nio均为对底层操作 * * 数据并不会发生改变 对于服务器而言通常需要使用nio 对付 * * 客户端使用io或者nio 还有aio异步io */public class Server { public static void main(String[] args) { //oldMethod(); //newMethodBlock(); newMethodUnBlock(); //selector(); } //阻塞的接收方法 public static void newMethodBlock(){ ServerSocketChannel ssc = null; SocketChannel sc = null; try { ssc = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress(9999)); sc = ssc.accept(); ByteBuffer bb = ByteBuffer.allocate(1024); while(true){ if(sc == null){ continue; } sc.read(bb); bb.flip(); System.out.println("接收数据"); System.out.println(new String(bb.array())); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ if(sc != null){ try { sc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(ssc != null){ try { ssc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //nio非阻塞接收方法 即注册接收器 public static void newMethodUnBlock(){ ServerSocketChannel ssc = null; Selector selector = null; ByteArrayOutputStream bos = null; try { bos = new ByteArrayOutputStream(); ssc = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress(9999)); ssc.configureBlocking(false); selector = selector.open(); ssc.register(selector, SelectionKey.OP_ACCEPT); Iterator<SelectionKey> it = null; SelectionKey key = null; while(true){ if(selector.select(3000) == 0){ System.out.println("尚未连接"); continue; } it = selector.selectedKeys().iterator(); while(it.hasNext()){ key = it.next(); Thread.sleep(500); if(key.isAcceptable()){ /** * 这里表示ssc处于可以连接状态 * * ssc设置为非阻塞状态,一旦客户端处于连接 这里就会触发 * * 一旦有新的客户端连接 这里的sc才会有返回值 * * 否者会一直为空 即后面的代码就没有什么用处 * * 注意这里不能注册Accept 只能注册read和write * * 可以注册多个 channel在关闭的时候会自动解除注册 */ ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(key.selector(), SelectionKey.OP_READ|SelectionKey.OP_WRITE,ByteBuffer.allocateDirect(1024)); } //这里是针对于连接生成的sc具备的读状态 if(key.isReadable()){ SocketChannel sc1 = (SocketChannel) key.channel(); ByteBuffer bb = (ByteBuffer) key.attachment(); int len = sc1.read(bb); if(len == -1){ sc1.close(); } bb.flip(); while(bb.hasRemaining()){ bos.write(bb.get()); } System.out.println(new String(bos.toByteArray(),0,len)); bos.reset(); bb.clear(); } if(key.isWritable()){ System.out.println("写状态"); } if(key.isConnectable()){ System.out.println("连接状态"); } /** * 此处是将处理过的数据移除 * * 下一次的循环会再次将注册的通道通道添加 * * 但是不会自动移除 需要手动移除 */ it.remove(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if(ssc != null){ try { ssc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(selector != null){ try { selector.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //io的接收方法 public static void oldMethod(){ ServerSocket ss = null; Socket socket = null; InputStream is = null; try { ss = new ServerSocket(9999); socket = ss.accept(); is = socket.getInputStream(); int len = 0; byte[] data = new byte[1024]; while((len = is.read(data)) != -1){ System.out.println(new String(data,0,len)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
需要注意的是 如果没有设置不阻塞的话,也就是阻塞,是会在accept处阻塞,如果设置了不阻塞,会直接返回,如果没有连接,那么就返回null 坚决不会阻塞
0 0
- java NIO socket编程简介
- Java NIO socket编程实例
- Java NIO socket编程实例
- Java Socket & Java NIO 编程解析
- Java Socket编程(五)NIO
- Java NIO socket编程实例 (转)
- Java Socket和ServerSocket编程 NIO
- JAVA Socket编程入门简介
- Socket简介以及Java Socket编程
- NIO的Socket编程
- Java NIO 与 Nio Socket
- Java NIO 之 NIO 简介
- java NIO非阻塞方式的Socket编程
- java NIO非阻塞方式的Socket编程
- java网络编程——socket、NIO、AIO
- JAVA 网络编程(2) SOCKET 非阻塞NIO示例
- java NIO非阻塞方式的Socket编程
- java TCP/IP Socket编程-----NIO--初识-----笔记8
- 伸展树(排列变换,uva 11922)
- 字符串空格处理
- Gradle出现Could not create task of type 'DependencyManagementReportTask'
- 1073.Scientific Notation (20)
- gradle连接shadowsock代理
- java NIO socket编程简介
- 二项堆 数据结构说解
- 连接文件
- 写给2017年的自己
- Tcp C/S架构实现聊天室(链表管理在线用户)(服务器)
- SGD的batch size多大是合适的?
- 过河问题
- Rails中使用ajax的两种方法及调试技巧
- Tcp C/S架构实现聊天室(链表管理在线用户)(客户端)