网络编程时,我们常见到同步(Sync)和异步(Async),阻塞(blocking)和非阻塞(non-blocking)四种调用模式:
①同步:
客户端发一个调用,再没有得到结果之前,该调用不返回,通俗来讲,就是必须做完前一件事情才可以 做下一件事情;
②异步:
当客户端发生一个异步请求的调用的时候,调用者不能立刻得到结果,实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者,例如ajax请求;
③阻塞
通俗的讲,做某件事情,知道完成,除非超时,如果没有完成,继续等待;当阻塞调用的时候,在调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,CPU不会给线程分配时间片,即线程暂停运行),函数只有在得到结果折后才会被 返回;
④非阻塞
指在不能得到结果之前,该函数不会阻塞当前线程,会立刻返回;
还是等快递的例子:如果用忙轮询的方法,每隔5分钟到A楼一层(内核缓冲区)去看快递来了没有。如果没来,立即返回。而快递来了,就放在A楼一层,等你去取。
传统IO的Socket的单线程通信,用非常经典的食堂例子来讲解,端口号相当于食堂大门,线程相当于服务员,在这个状态下,一个客户需要有一个服务员来服务,这样显然是不合理的,假如有100个顾客的话,就需要100服务员,这样非常浪费系统资源,代码如下:
package IoSocket; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /** * Created by Taoyongpan on 2017/10/23. * 传统的IO是阻塞IO,每多一个用户就要创建一个新的线程,单线程模式 */ public class TraditionalSocketDemo { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务器启动。。。。"); while (true){ //接收客户端的连接 ,套接字 Socket socket = serverSocket.accept(); System.out.println("有新的客户端连接"); InputStream in = null; try { in = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } byte[] b = new byte[1024]; while (true){ int data = 0; data = in.read(b); if (data!=-1){ String info = new String(b,0,data); System.out.println(info); }else { break; } } } } }
当程序运行的时候:
这时用命令窗口创建一个用户,我这里面的端口号是8888,我们创建客户的语句是:telnet localhost 8888,如图所示:
输入 CTRL+]的命令 进入字符串发送页面。原来的页面只可以发送字符;
send +自己所要发送的内容,如上图所示;
因为这个代码写的是单线程模式的,当我们再创建一个新的客户的时候,就会陷入等待,只有关闭上一个现成的时候,新建客户的消息的才可以发送,如下图所示:
我们也可以创建一个线程池,来实现多线程,代码如下:
package IoSocket; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by Taoyongpan on 2017/10/24. * 传统的IO是阻塞IO,每多一个用户就要创建一个新的线程 */ public class TraditionSocketDemo1 { public static void main(String[] args) throws IOException { //多线程方法,创建一个线程池 ExecutorService es = Executors.newCachedThreadPool(); ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务器启动。。。。"); while (true){ //接收客户端的连接 ,套接字 Socket socket = serverSocket.accept(); System.out.println("有新的客户端连接"); es.execute(new Runnable() { @Override public void run() { InputStream in = null; try { in = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } byte[] b = new byte[1024]; while (true){ int data = 0; try { data = in.read(b); } catch (IOException e) { e.printStackTrace(); } if (data!=-1){ String info = new String(b,0,data); System.out.println(info); }else { break; } } } }); } } }
重复运行上面的测试步骤就可以进行操作:
测试如下图所示:
NIO是非阻塞的IO,相对于传统IO,新增了selector、channel和buffer,还用食堂的例子来讲解,我们的channel就像食堂的大门,一个食堂的服务员可以服务多个客户,这个过程用selector来调度,例如在 客户A点菜的时候,接待了客户B,代码如下:
package IoSocket; import java.io.IOException; 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.util.Iterator; /** * Created by Taoyongpan on 2017/10/23. * nio,增加了selector,channel ,buffer,非阻塞 */ public class NioSocketDemo { private Selector selector;//通道选择器 public static void main(String[] args) throws IOException { NioSocketDemo nioSocketDemo = new NioSocketDemo(); nioSocketDemo.initServer(8888); nioSocketDemo.listenSelector(); } public void initServer(int port) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false);//设置成非阻塞 serverSocketChannel.socket().bind(new InetSocketAddress(port)); this.selector = Selector.open(); //注册监听器 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//注册监听连接请求 System.out.println("服务已启动。。。"); } public void listenSelector() throws IOException { //循环监听selector while (true){ //等待客户连接 //select模型,多路服用 this.selector.select(); this.selector.selectedKeys().iterator(); Iterator<SelectionKey> it = this.selector.selectedKeys().iterator(); while (it.hasNext()){ SelectionKey skey = it.next(); it.remove();//把当前的元素remove掉 //处理请求 handler(skey); } } } private void handler(SelectionKey skey) throws IOException { if (skey.isAcceptable()){ //处理客户端连接事件 ServerSocketChannel serverChannel = (ServerSocketChannel)skey.channel(); SocketChannel socketChannel = serverChannel.accept(); System.out.println("新客户连接上来了"); socketChannel.configureBlocking(false);//设置为非阻塞 //接收客户端发送的信息,需要给通道设置读的权限 socketChannel.register(selector,SelectionKey.OP_READ); }else if (skey.isReadable()){ //处理读的事件 SocketChannel socketChannel = (SocketChannel) skey.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024);//初始化一个缓存 int data = socketChannel.read(byteBuffer); if (data>0){ String info = new String(byteBuffer.array(),"GBK").trim(); System.out.println("客户端消息"+info); }else { System.out.println("客户端关闭了"); skey.cancel();//把这个连接清除掉 } } } }
这个的运行效果和传统IO的多线程的运行结果是一样的,这里就不再进行展示;
相关推荐
在Java编程领域,NIO(Non-blocking Input/Output)是一种重要的网络编程模型,与传统的IO模型相比,它提供了更高的性能和更低的系统资源消耗。本示例中的"加法服务器"是一个利用NIO Channel实现的简单应用,它展示...
在Java编程中,NIO(New Input/Output)提供了一种不同于传统IO模型的I/O操作方式,其核心特点是能够进行多路复用,即一个线程可以同时处理多个连接,这使得NioSocket在高并发场景下具有较好的性能表现。 服务器端...
在Java编程领域,IO(Input/Output)和NIO(Non-blocking Input/Output)是两种不同的I/O模型,它们在处理数据输入和输出时有着显著的差异。本教程旨在帮助NIO初学者理解这两种模型的核心概念及其实际应用,通过具体...
Java IO、NIO以及NIO.2是Java中用于处理输入/输出操作的三种主要机制。本书《Java IO, NIO and NIO.2》旨在深入浅出地介绍这些机制,同时书中内容均为英文。接下来将详细介绍这些知识点。 **Java IO** Java IO是...
NIO与传统的IO模型不同,它提供了对多路复用器的支持,如Java的Selector类,可以同时监控多个通道的状态变化,从而提高了系统在高并发环境下的性能。在Socket编程中,NIO使得服务器可以处理更多的连接请求,而无需为...
### Java NIO网络编程核心知识点解析 #### 非阻塞式Socket通信:Java NIO的革命性突破 从JDK 1.4版本开始,Java引入了NIO(Non-blocking I/O)API,这标志着Java网络编程的一个重大转折点。传统上,基于阻塞I/O的...
#### 一、NIO与传统IO的区别及优势 在探讨如何使用Java NIO实现Socket通信之前,我们需要先理解NIO(Non-blocking I/O,非阻塞I/O)与传统阻塞I/O之间的区别。 **传统阻塞I/O模型**:在传统的Java IO编程中,当...
**NIO(New Input/Output)编程技术指南** 在Java世界中,NIO(New Input/Output)是一种从Java 1.4...《NIO与Socket编程技术指南》_高洪岩.pdf这本书将为你提供全面的NIO知识和实践指导,帮助你掌握这一关键技术。
在NIO中,Socket通信不再局限于传统的`java.net.Socket`和`java.net.ServerSocket`,而是通过`java.nio.channels.SocketChannel`和`java.nio.channels.ServerSocketChannel`进行。 1. **SocketChannel**:这是NIO中...
NIO(Non-blocking I/O)是Java提供的一个高效I/O模型,相较于传统的IO模型,NIO具有非阻塞、多路复用等特性,能够更好地处理大量并发连接。本实例"socket通信NIO代理模式demo"将展示如何利用NIO来构建一个高性能的...
Java NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java应用程序提供了非阻塞I/O操作的能力,与传统的IO模型(基于流的I/O和基于缓冲区的I/O)相比,NIO具有更高的效率和灵活性。在Java NIO中,数据是以通道...
Java Socket编程是网络编程中的重要组成部分,主要用于实现客户端与服务器之间的通信。在Java中,Socket是基于TCP协议的,提供了一种可靠的、基于字节流的双向通信方式。本资料包含的"Java源码:Socket编程"是一个...
在Java世界中,网络编程是一个不可或缺的部分,而Mina NIO(Non-blocking I/O)Socket库则是Java开发者实现高性能、高并发网络服务的重要工具。本文将深入探讨Mina NIO Socket的核心概念、工作原理以及在实际项目中...
总之,Java网络编程与Socket编程是Java开发者必须掌握的技术之一。理解其原理,熟练运用相关API,能帮助我们开发出高效、稳定的网络应用程序。在实际项目中,根据需求选择合适的通信方式,结合多线程、NIO等技术,...
Java Socket编程是网络编程的基础,它提供了在两个应用程序之间建立通信连接的能力。在这个场景中,我们讨论的是如何使用Java的Socket来实现文件上传功能,即从客户端将文件发送到服务器,然后保存到服务器的数据库...
它与传统的BIO(Blocking IO)模型不同,NIO提供了更高效的数据读写方式,特别适合于高并发、低延迟的网络应用,如Socket服务器的构建。本篇将基于给定的标题“采用NIO实现一个Socket服务器”来详细阐述如何使用NIO...
**BIO**,即传统的阻塞I/O模型,在Java中表现为`java.io`包中的类,如`Socket`和`ServerSocket`。在BIO中,每个连接都需要一个独立的线程进行处理,当服务端接收客户端连接请求时,会阻塞直到数据读取或写入完成。...
Java NIO(New IO)是Java 1.4版本引入的一种新的I/O API,它提供了与标准Java IO API不同的I/O工作方式。...不过,NIO的学习曲线较陡峭,理解和使用起来相比传统的Socket编程需要更多的实践和调试。