当前位置: 首页 > news >正文

苏州网页服务开发与网站建设佛山市桂城建设局网站

苏州网页服务开发与网站建设,佛山市桂城建设局网站,网页设计教程完整,陕西有没有做网站好的公司目录 原生JDK网络编程BIO BIO通信模型服务端代码 BIO通信模型客户端代码 伪异步模型服务端代码#xff08;客户端跟之前一致#xff09; 原生JDK网络编程NIO 什么是NIO#xff1f; NIO和BIO的主要区别 阻塞与非阻塞IO NIO之Reactor模式 NIO中Reactor模式的基本组成…目录 原生JDK网络编程BIO BIO通信模型服务端代码 BIO通信模型客户端代码 伪异步模型服务端代码客户端跟之前一致 原生JDK网络编程NIO 什么是NIO NIO和BIO的主要区别 阻塞与非阻塞IO NIO之Reactor模式 NIO中Reactor模式的基本组成部分 NIO代码实现 原生JDK网络编程BIO BIO意为Blocking I/O即阻塞的 I/O。在BIO中类 ServerSocket 负责绑定 IP 地址启动监听端口等待客户连接客户端 Socket 类的实例发起连接操作ServerSocket 接受连接后产生一个新的服务端socket实例负责和客户端 socket 实例通过输入和输出流进行通信。 BIO的阻塞主要体现在两个地方 1. 若一个服务器启动就绪那么主线程就一直在等待着客户端的连接这个等待过程中主线程就一直在阻塞。 2. 在连接建立之后在读取到socket信息之前线程也是一直在等待一直处于阻塞的状态下的。 传统BIO通信模型采用 BIO 通信模型的服务端通常由一个独立的 Acceptor 线程负责监听客户端的连接它接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理处理完成后通过输出流返回应答给客户端线程销毁。即典型的一请求一应答模型同时数据的读取写入也必须阻塞在一个线程内等待其完成。 BIO通信模型服务端代码 public class Server {public static void main(String[] args) throws IOException {//服务端启动必备ServerSocket serverSocket new ServerSocket();//表示服务端在哪个端口上监听serverSocket.bind(new InetSocketAddress(10001));System.out.println(Start Server ....);try{while(true){new Thread(new ServerTask(serverSocket.accept())).start();}}finally {serverSocket.close();}}//每个和客户端的通信都会打包成一个任务交个一个线程来执行private static class ServerTask implements Runnable{private Socket socket null;public ServerTask(Socket socket){this.socket socket;}Overridepublic void run() {//实例化与客户端通信的输入输出流try(ObjectInputStream inputStream new ObjectInputStream(socket.getInputStream());ObjectOutputStream outputStream new ObjectOutputStream(socket.getOutputStream())){//接收客户端的输出也就是服务器的输入String userName inputStream.readUTF();System.out.println(Accept client message:userName);//服务器的输出也就是客户端的输入outputStream.writeUTF(Hello,userName);outputStream.flush();}catch(Exception e){e.printStackTrace();}finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} } BIO通信模型客户端代码 public class Client {public static void main(String[] args) throws IOException {//客户端启动必备Socket socket null;//实例化与服务端通信的输入输出流ObjectOutputStream output null;ObjectInputStream input null;//服务器的通信地址InetSocketAddress addr new InetSocketAddress(127.0.0.1,10001);try{socket new Socket();socket.connect(addr);//连接服务器System.out.println(Connect Server success!!);output new ObjectOutputStream(socket.getOutputStream());input new ObjectInputStream(socket.getInputStream());System.out.println(Ready send message.....);/*向服务器输出请求*/output.writeUTF(zhangsan);output.flush();//接收服务器的输出System.out.println(input.readUTF());}finally{if (socket!null) socket.close();if (output!null) output.close();if (input!null) input.close();}} } 根据以上模型编写的代码最大的问题就是缺乏弹性伸缩能力当客户端并发访问量增加后服务端的线程 个数和客户端并发访问数呈 1:1 的正比关系Java 中的线程也是比较宝贵的系统资源线程数量快速膨胀后系统的性能将急剧下降。 我们可以使用线程池来管理这些线程使用 CachedThreadPool 线程池其实除了能自动帮我们管理线程复用看起来也就像是 1:1 的客户 端线程数模型。而使用 FixedThreadPool 我们就有效的控制了线程的最大数量保证了系统有限的资源的控制实现了N:M的伪异步 I/O 模型。 伪异步模型服务端代码客户端跟之前一致 public class ServerPool {private static ExecutorService executorService Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());public static void main(String[] args) throws IOException {//服务端启动必备ServerSocket serverSocket new ServerSocket();//表示服务端在哪个端口上监听serverSocket.bind(new InetSocketAddress(10001));System.out.println(Start Server ....);try{while(true){executorService.execute(new ServerTask(serverSocket.accept()));}}finally {serverSocket.close();}}//每个和客户端的通信都会打包成一个任务交个一个线程来执行private static class ServerTask implements Runnable{private Socket socket null;public ServerTask(Socket socket){this.socket socket;}Overridepublic void run() {//实例化与客户端通信的输入输出流try(ObjectInputStream inputStream new ObjectInputStream(socket.getInputStream());ObjectOutputStream outputStream new ObjectOutputStream(socket.getOutputStream())){//接收客户端的输出也就是服务器的输入String userName inputStream.readUTF();System.out.println(Accept client message:userName);//服务器的输出也就是客户端的输入outputStream.writeUTF(Hello,userName);outputStream.flush();}catch(Exception e){e.printStackTrace();}finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} } 以上这种实现正因为限制了线程数量如果发生读取数据较慢时比如数据量大、网络传输慢等大量并发的情况下其他接入的消息只能一直等待这就是最大的弊端。 原生JDK网络编程NIO 什么是NIO NIO库是在JDK 1.4中引入的。NIO弥补了原来的BIO的不足它在标准Java代码中提供了高速的、面向块的I/O。NIO被称为no-blocking io或者new io都说得通。 NIO和BIO的主要区别 面向流与面向缓冲 Java NIO 和 IO 之间第一个最大的区别是IO 是面向流的NIO 是面向缓冲区的。 Java IO 面向流意味着每次从流中读一个或多个字节直至读取所有字节它们没有被缓存在任何地方。此外它不能前后移动流中的数据。如果需要前后移动从流中读取的数据需要先将它缓存到一个缓冲区。 Java NIO 的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是还需要检查是否该缓冲区中包含所有需要处理的数据。而且需确保当更多的数据读入缓冲区时不要覆盖缓冲区里尚未处理的数据。 阻塞与非阻塞IO Java NIO 的非阻塞模式使一个线程从某通道发送请求读取数据但是它仅能得到目前可用的数据如果目前没有数据可用时就什么都不会获取。而不是保持线程阻塞所以直至数据变的可以读取之前该线程可以继续做其他的事情。非阻塞写也是如此。一个线程请求写入一些数据到某通道但不需要等待它完全写入这个线程同时可以去做别的事情。线程通常将非阻塞 IO 的空闲时间用于在其它通道上执行 IO 操作所以一个单独的线程现在可以管理多个输入和输出通道channel。 NIO之Reactor模式 Java NIONew I/O中使用了 Reactor 模式。 Reactor 模式是一种事件处理模式它通过一个称为 Reactor 的中心调度器来响应输入事件并将事件分发给相应的处理程序也称为处理器或回调函数进行处理。 NIO中Reactor模式的基本组成部分 Selector选择器        Selector是 Reactor 模式的核心负责监听各个通道上的事件如连接、接收、读取和写入事件。通过 Selector一个单独的线程可以有效地管理多个通道使得系统可以在一个线程内同时处理多个连接。Channel通道         Channel 是数据的载体可以是文件、套接字等。通道向 Selector 注册告诉 Selector 哪些事件它关心然后 Selector 将根据事件的发生情况通知对应的通道。SelectionKey选择键         当一个通道向 Selector 注册时会创建一个 SelectionKey 对象。这个对象包含了通道和 Selector 之间的关联关系以及通道感兴趣的事件如OP_READ读、OP_WRITE写、OP_CONNECT连接、OP_ACCEPT接收连接事件。当事件发生时Selector 将通知对应的 SelectionKey通过 SelectionKey 可以获取关联的通道和发生的事件类型。Handler处理器         处理器是用户编写的处理事件的逻辑它通过回调函数的方式响应事件。当事件发生时Reactor 模式调用处理器的回调函数来执行相应的业务逻辑。 在Java NIO中应用程序通过将通道注册到 Selector然后在事件发生时由 Reactor 调用相应的处理器来处理。这种模型使得在单线程内可以有效地处理多个并发连接提高了系统的性能和扩展性。 NIO代码实现 服务端 public class NioServer {private static NioServerHandle nioServerHandle;public static void main(String[] args){nioServerHandle new NioServerHandle(8888);new Thread(nioServerHandle,Server).start();} } public class NioServerHandle implements Runnable{private volatile boolean started;private ServerSocketChannel serverSocketChannel;private Selector selector;/*** 构造方法* param port 指定要监听的端口号*/public NioServerHandle(int port) {try {/*创建选择器的实例*/selector Selector.open();/*创建ServerSocketChannel的实例*/serverSocketChannel ServerSocketChannel.open();/*设置通道为非阻塞模式*/serverSocketChannel.configureBlocking(false);/*绑定端口*/serverSocketChannel.socket().bind(new InetSocketAddress(port));/*注册事件表示关心客户端连接*/serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);started true;System.out.println(服务器已启动端口号port);} catch (IOException e) {e.printStackTrace();}}Overridepublic void run() {while(started){try {/*获取当前有哪些事件*/selector.select(1000);/*获取事件的集合*/SetSelectionKey selectionKeys selector.selectedKeys();IteratorSelectionKey iterator selectionKeys.iterator();while(iterator.hasNext()){SelectionKey key iterator.next();/*我们必须首先将处理过的 SelectionKey 从选定的键集合中删除。如果我们没有删除处理过的键那么它仍然会在主集合中以一个激活的键出现这会导致我们尝试再次处理它。*/iterator.remove();handleInput(key);}} catch (IOException e) {e.printStackTrace();}}}/*处理事件的发生*/private void handleInput(SelectionKey key) throws IOException {if(key.isValid()){/*处理新接入的客户端的请求*/if(key.isAcceptable()){/*获取关心当前事件的Channel*/ServerSocketChannel ssc (ServerSocketChannel) key.channel();/*接受连接*/SocketChannel sc ssc.accept();System.out.println(建立连接);sc.configureBlocking(false);/*关注读事件*/sc.register(selector,SelectionKey.OP_READ);}/*处理对端的发送的数据*/if(key.isReadable()){SocketChannel sc (SocketChannel) key.channel();/*创建ByteBuffer开辟一个缓冲区*/ByteBuffer buffer ByteBuffer.allocate(1024);/*从通道里读取数据然后写入buffer*/int readBytes sc.read(buffer);if(readBytes0){/*将缓冲区当前的limit设置为position,position0用于后续对缓冲区的读取操作*/buffer.flip();/*根据缓冲区可读字节数创建字节数组*/byte[] bytes new byte[buffer.remaining()];/*将缓冲区可读字节数组复制到新建的数组中*/buffer.get(bytes);String message new String(bytes,UTF-8);System.out.println(服务器收到消息message);/*处理数据*/String result Const.response(message);/*发送应答消息*/doWrite(sc,result);}else if(readBytes0){/*取消特定的注册关系*/key.cancel();/*关闭通道*/sc.close();}}}}/*发送应答消息*/private void doWrite(SocketChannel sc,String response) throws IOException {byte[] bytes response.getBytes();ByteBuffer buffer ByteBuffer.allocate(bytes.length);buffer.put(bytes);buffer.flip();sc.write(buffer);}public void stop(){started false;} }客户端 public class NioClient {private static NioClientHandle nioClientHandle;public static void start(){nioClientHandle new NioClientHandle(127.0.0.1,8888);new Thread(nioClientHandle,client).start();}//向服务器发送消息public static boolean sendMsg(String msg) throws Exception{nioClientHandle.sendMsg(msg);return true;}public static void main(String[] args) throws Exception {start();Scanner scanner new Scanner(System.in);while(NioClient.sendMsg(scanner.next()));} } public class NioClientHandle implements Runnable{private String host;private int port;private volatile boolean started;private Selector selector;private SocketChannel socketChannel;public NioClientHandle(String ip, int port) {this.host ip;this.port port;try {/*创建选择器的实例*/selector Selector.open();/*创建ServerSocketChannel的实例*/socketChannel SocketChannel.open();/*设置通道为非阻塞模式*/socketChannel.configureBlocking(false);started true;} catch (IOException e) {e.printStackTrace();}}public void stop(){started false;}Overridepublic void run() {try{doConnect();}catch(IOException e){e.printStackTrace();System.exit(1);}//循环遍历selectorwhile(started){try{//无论是否有读写事件发生selector每隔1s被唤醒一次selector.select(1000);//获取当前有哪些事件可以使用SetSelectionKey keys selector.selectedKeys();//转换为迭代器IteratorSelectionKey it keys.iterator();SelectionKey key null;while(it.hasNext()){key it.next();/*我们必须首先将处理过的 SelectionKey 从选定的键集合中删除。如果我们没有删除处理过的键那么它仍然会在主集合中以一个激活的键出现这会导致我们尝试再次处理它。*/it.remove();try{handleInput(key);}catch(Exception e){if(key ! null){key.cancel();if(key.channel() ! null){key.channel().close();}}}}}catch(Exception e){e.printStackTrace();System.exit(1);}}//selector关闭后会自动释放里面管理的资源if(selector ! null)try{selector.close();}catch (Exception e) {e.printStackTrace();}}//具体的事件处理方法private void handleInput(SelectionKey key) throws IOException{if(key.isValid()){//获得关心当前事件的channelSocketChannel sc (SocketChannel) key.channel();//连接事件if(key.isConnectable()){if(sc.finishConnect()){socketChannel.register(selector,SelectionKey.OP_READ);}else System.exit(1);}//有数据可读事件if(key.isReadable()){//创建ByteBuffer并开辟一个1M的缓冲区ByteBuffer buffer ByteBuffer.allocate(1024);//读取请求码流返回读取到的字节数int readBytes sc.read(buffer);//读取到字节对字节进行编解码if(readBytes0){//将缓冲区当前的limit设置为position,position0// 用于后续对缓冲区的读取操作buffer.flip();//根据缓冲区可读字节数创建字节数组byte[] bytes new byte[buffer.remaining()];//将缓冲区可读字节数组复制到新建的数组中buffer.get(bytes);String result new String(bytes,UTF-8);System.out.println(客户端收到消息 result);}//链路已经关闭释放资源else if(readBytes0){key.cancel();sc.close();}}}}private void doWrite(SocketChannel channel,String request)throws IOException {//将消息编码为字节数组byte[] bytes request.getBytes();//根据数组容量创建ByteBufferByteBuffer writeBuffer ByteBuffer.allocate(bytes.length);//将字节数组复制到缓冲区writeBuffer.put(bytes);//flip操作writeBuffer.flip();//发送缓冲区的字节数组/*关心事件和读写网络并不冲突*/channel.write(writeBuffer);}private void doConnect() throws IOException{/*非阻塞的连接*/if(socketChannel.connect(new InetSocketAddress(host,port))){socketChannel.register(selector,SelectionKey.OP_READ);}else{socketChannel.register(selector,SelectionKey.OP_CONNECT);}}//写数据对外暴露的APIpublic void sendMsg(String msg) throws Exception{doWrite(socketChannel, msg);} }
http://www.pierceye.com/news/131076/

相关文章:

  • 有口碑的坪山网站建设王野天 演员
  • 建e网怎么赚钱衡水网站优化
  • 做牙科设计的网站域名一定要备案才能用吗
  • 哪个网站做团购要求低点河北省住房和城乡建设厅网站
  • 华为商城网站建设世界杯大数据
  • 网站流量指标高埗镇仿做网站
  • 网站建设颊算校园网站的作用
  • 云南公司网站制作外贸网站推广外包
  • 甘肃住房建设厅的网站数据中心idc机房
  • wordpress开发视频网站模板下载wordpress qq 微信登录
  • 上海网站建设网站营销推广费计入什么科目
  • 云南培训网站建设网站建设的公司太多了
  • 洛阳网站建设招聘信息ppt设计师兼职
  • 建工网官方网站电子商务网站设计岗位主要是
  • 保险网站建设平台青岛设计公司排名
  • 伊利网站建设评价做的最好的宠物网站
  • 沈阳的网站制作公司哪家好常用设计资源网站
  • 做网站需要什么技术文化传媒公司 网站备案
  • 郑州市建设厅网站html5 网站开发定制
  • 网站制作网站建站公司用wordpress
  • 做资讯网站盈利措美网站建设
  • 山东建设工程执业证书查询网站建网是什么
  • 大型服装网站建设wordpress留言板模版
  • 延安做网站沈阳学网站制作学校
  • 网站添加新闻网站免费正能量软件不良
  • asp c 网站开发互动网门户网站建设
  • 图书馆网站结构怎么做国外超酷设计网站
  • 网站开发软件搭配学室内设计去哪好
  • 南通营销网站制作河南省大型项目建设办公室网站
  • 黄山网站建设怎么做seo快速优化技术