概念理解:
Netty是基于NIO的框架
传统IO与NIO的区别:
1、传统IO会造成阻塞点:
2、单一的客户端处理消息
解决阻塞问题:建立线程池,达到收到一个消息就建立一个客户端交互
3、 用socket实现长连接的缺陷:
(1)消耗巨大
(2)没建立一次交互,就会产生一个新的线程池连接,线程长时间被一个客户端占用 (举例:一个餐厅,每来一个客户,都分配一个单独的服务员,为其服务)
传统socket可以做短连接的服务器。
4、单线程情况下只能有一个客户端
5、用线程池可以有多个客户端连接,但非常消耗性能
实战一:单线程实例
1 package com.OIO; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 import java.util.concurrent.ExecutorService; 7 import java.util.concurrent.Executors; 8 /** 9 * 传统socket服务端 10 * @author -琴兽- 11 * 12 */ 13 public class OioServer { 14 15 @SuppressWarnings("resource") 16 public static void main(String[] args) throws Exception { 17 18 // ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); 19 //创建socket服务,监听10101端口 20 ServerSocket server=new ServerSocket(10101); 21 System.out.println("服务器启动!"); 22 while(true){ 23 //获取一个套接字(阻塞) 24 final Socket socket = server.accept(); 25 System.out.println("来个一个新客户端!"); 26 27 //业务处理 28 handler(socket); 29 30 31 } 32 } 33 34 /** 35 * 读取数据 36 * @param socket 37 * @throws Exception 38 */ 39 public static void handler(Socket socket){ 40 try { 41 byte[] bytes = new byte[1024]; 42 InputStream inputStream = socket.getInputStream(); 43 44 while(true){ 45 //读取数据(阻塞) 46 int read = inputStream.read(bytes); 47 if(read != -1){ 48 System.out.println(new String(bytes, 0, read)); 49 }else{ 50 break; 51 } 52 } 53 } catch (Exception e) { 54 e.printStackTrace(); 55 }finally{ 56 try { 57 System.out.println("socket关闭"); 58 socket.close(); 59 } catch (IOException e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 }
其中server.accept();和inputStream.read(bytes);会造成阻塞.
只能有一个客户端与服务端进行交互
window+R 进入cmd 命令界面,输入telnet 127.0.0.1 10101 进入创建连接,ctrl+] 进入命令界面,发送send hello 回车,就会向服务端发送数据.
解决方法,增加线程池操作
实例二:线程池实现连接交互
1 package com.OIO; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.net.ServerSocket; 6 import java.net.Socket; 7 import java.util.concurrent.ExecutorService; 8 import java.util.concurrent.Executors; 9 10 /** 11 * 传统socket服务端 12 * 13 * @author -琴兽- 14 */ 15 public class OioServer { 16 17 @SuppressWarnings("resource") 18 public static void main(String[] args) throws Exception { 19 20 /** 21 * 创建线程池交互 22 */ 23 ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); 24 25 //创建socket服务,监听10101端口 26 ServerSocket server = new ServerSocket(10101); 27 System.out.println("服务器启动!"); 28 while (true) { 29 //获取一个套接字(阻塞) 30 final Socket socket = server.accept(); 31 System.out.println("版本二 :*****来个一个新客户端!**********"); 32 33 newCachedThreadPool.execute(new Runnable() { 34 @Override 35 public void run() { 36 //业务处理 37 handler(socket); 38 } 39 }); 40 41 } 42 } 43 44 /** 45 * 读取数据 46 * 47 * @param socket 48 * @throws Exception 49 */ 50 public static void handler(Socket socket) { 51 try { 52 byte[] bytes = new byte[1024]; 53 InputStream inputStream = socket.getInputStream(); 54 55 while (true) { 56 //读取数据(阻塞) 57 int read = inputStream.read(bytes); 58 if (read != -1) { 59 System.out.println(new String(bytes,0,read)); 60 } else { 61 break; 62 } 63 } 64 } catch (Exception e) { 65 e.printStackTrace(); 66 } finally { 67 try { 68 System.out.println("socket关闭"); 69 socket.close(); 70 } catch (IOException e) { 71 e.printStackTrace(); 72 } 73 } 74 } 75 }
可以实现多个客户端接入连接数据交互.但是却是每次建立一个线程,极大耗费资源