网络模式选哪个好(手机5g网络模式选哪个好)

最近有很多读者朋友对网络模式选哪个好有疑问。由部分网友整理出相关内容希望能够解答你的疑惑,关于手机5g网络模式选哪个好,本站也已经为你找到了问题的答案,希望能帮助到你。

IO模型

IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式:BIO,NIO,AIO

BIO(Blocking IO )

同步阻塞模型,一个客户端连接对应一个处理线程

网络模式选哪个好(手机5g网络模式选哪个好)插图

BIO代码示例:

import java.net.ServerSocket;import java.net.Socket;import java.util.logging.Handler; public class SocketServer { public static void main(String[] args) throws Exception { ServerSocket serverSocket=new ServerSocket(9000); while (true){ System.out.println("等待连接"); //阻塞连接 Socket clientSocket=serverSocket.accept(); System.out.println("有客户端连接。。。");// handle(clientSocket); new Thread(new Runnable() { @Override public void run() { try { handle(clientSocket); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } public static void handle(Socket clientSocket) throws Exception{ byte[] bytes=new byte[1024]; System.out.println("准备read。。"); //接收客户端的数据,阻塞方法,没有数据可读时就阻塞 int read=clientSocket.getInputStream().read(bytes); System.out.println("read 完毕。"); if (read !=-1){ System.out.println("接收到客户端数据:" + new String(bytes,0,read)); } clientSocket.getOutputStream().write("helloClient".getBytes()); clientSocket.getOutputStream().flush(); }}

//客户端代码 import java.io.IOException;import java.net.Socket; public class SocketClient { public static void main(String[] args) throws IOException { Socket socket=new Socket("localhost", 9000); //向服务端发送数据 socket.getOutputStream().write("HelloServer".getBytes()); socket.getOutputStream().flush(); System.out.println("向服务端发送数据结束"); byte[] bytes=new byte[1024]; //接收服务端回传的数据 socket.getInputStream().read(bytes); System.out.println("接收到服务端的数据:" + new String(bytes)); socket.close(); }}

缺点:

从上面的代码我们可以看出来,BIO代码中连接事件和读写数据事件都是阻塞的,所以这种模式的缺点非常的明显

1、如果我们连接完成以后,不做读写数据操作会导致线程阻塞,浪费资源

2、如果没来一个连接我们都需要启动一个线程处理,那么会导致服务器线程太多,压力太大,比如C10K;

应用场景:

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,但是程序比较简单。

NIO(Non Blocking IO)

同步非阻塞模型,服务器实现模式为一个线程可以处理多个请求连接,客户端发送的连接请求都会注册到多路复用器(selector)上,多路复用器轮询到连接有IO请求就进行处理,JDK1.4开始引入。

//没有引入多路复用器的代码 import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class NioServer { static List<SocketChannel> channelList=new ArrayList<>(); public static void main(String[] args) throws Exception { //创建NIO ServerSocketChannel serverSocket=ServerSocketChannel.open(); serverSocket.socket().bind(new InetSocketAddress(9000)); //设置非阻塞 serverSocket.configureBlocking(false); System.out.println("服务启动。。"); while (true) { //非阻塞模式accept方法不会阻塞,否则会阻塞 //NIO的非阻塞模式是由操作系统内部实现,底层调用了Linux内核的accept函数 SocketChannel socketChannel=serverSocket.accept(); if (socketChannel !=null) { System.out.println("连接成功"); //设置socketchannel为非阻塞 socketChannel.configureBlocking(false); //保存客户端连接到list channelList.add(socketChannel); } //遍历连接读数据 Iterator<SocketChannel> iterator=channelList.iterator(); while (iterator.hasNext()) { SocketChannel sc=iterator.next(); ByteBuffer byteBuffer=ByteBuffer.allocate(128); //非阻塞模式read 方式不会阻塞 否则会阻塞 int len=sc.read(byteBuffer); if (len > 0) { System.out.println("接收到消息:" + new String(byteBuffer.array())); } else if (len==-1) { // 如果客户端断开,把socket从集合中去掉 iterator.remove(); System.out.println("客户端断开连接"); } } } }}

缺点:

如果连接数太多的话,会有大量的无效遍历,假如有10000个连接,其中只有1000个 连接有写数据,但是 由于其他9000个连接并没有断开看我们还是每次轮询遍历一万次,其中有 十分之一的遍历都是无效的,这显然是一个非常浪费资源的做法。

NIO引入多路复用器的代码示例:

package com.jack.nio; 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.security.Key;import java.util.Iterator;import java.util.Set; public class NioSelectorServer { public static void main(String[] args) throws Exception { //创建NIO ServerSocketChannle ServerSocketChannel serverSocket=ServerSocketChannel.open(); serverSocket.bind(new InetSocketAddress(9000)); //设置ServerSocketChannel为非阻塞 serverSocket.configureBlocking(false); //打开Selector处理channel,即创建epoll Selector selector=Selector.open(); //把ServerSocketChannel注册selector上,并且select对客户端accept连接操作感兴趣 serverSocket.register(selector, SelectionKey.OP_ACCEPT); System.out.println("服务启动"); // while (true) { //阻塞等待需要处理的事件发生 selector.select(); //获取selector中注册的全部事件的SelectionKey实例 Set<SelectionKey> selectionKeys=selector.selectedKeys(); Iterator<SelectionKey> iterator=selectionKeys.iterator(); //遍历selectionKeys对事件进行处理 while (iterator.hasNext()) { SelectionKey key=iterator.next(); //如果是accept事件,则进行连接获取和事件注册 if (key.isAcceptable()) { ServerSocketChannel server=(ServerSocketChannel) key.channel(); SocketChannel socketChannel=server.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); System.out.println("客户端连接成功"); } else if (key.isReadable()) { //进行数据读取 SocketChannel socketChannel=(SocketChannel) key.channel(); ByteBuffer byteBuffer=ByteBuffer.allocate(128); int len=socketChannel.read(byteBuffer); // 如果有数据,把数据打印出来 if (len > 0) { System.out.println("接收到消息:" + new String(byteBuffer.array())); } else if (len==-1) { // 如果客户端断开连接,关闭Socket System.out.println("客户端断开连接"); socketChannel.close(); } } //从事件集合里删除本次处理的key,防止下次select重复处理 iterator.remove(); } } }}

上面代码是利用NIO一个线程处理所有请求,这种单个线程处理的方式肯定是存在问题的,例如现在有10w个请求中,有1w个连接进行读写数据,那么SelectionKey就会有1w个请求,所以我们需要循环这1w个事件进行处理,比较费时间,如果这个时候再有连接进来,只能阻塞。

点击查看原文,获取更多福利!

https://developer.aliyun.com/article/1094014?utm_content=g_1000365505

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。