io、nio、tcp协议、socket、websocket、netty、tomcat

io->socket->应用tomcat(7.0版本Tomcat的底层是Socket编程)
nio->SocketChannel->tomcat(8.0版本)
tcp协议->socket-netty
socket(网络通信)
磁盘与IO基础知识:http://t.zoukankan.com/iwehdio-p-14248593.html
nio介绍:https://baijiahao.baidu.com/s?id=1709430016589717829&wfr=spider&for=pc
    https://www.jb51.net/article/211036.htm
    
一.慨念
    1.Buffer
        ByteBuffer详解:https://blog.csdn.net/t000818/article/details/79023134
        allocate方式
            核心参数capacity:
            核心参数 position:
            核心参数limit:
        allocateDirect方式
    2.Channel
        1.FileChannel file
        2.SocketChannel与ServerSocketChannel TCP
        3.DatagramChannel UDP
        4.Pipe
    3.Selector
一.nio比io快的原理
个人理解:
1、io是面向流的,字节流和字符流,其读与写是频繁与磁盘交互,是用户态和内核态频繁切换,也就是io是用户态,不能直接操作内核,需要操作系统调用内核来读写磁盘,切换本身就耗时;
nio是面向缓冲区的,使用内存映射,直接操作内存中数据(类似于c语言中allocateMemery等方法,这一点类似cas直接操作内存),避免了用户态和内核态的频繁奇切换
2、io是线程阻塞的,一个连接或者说一个线程读取,在没有数据之后进入阻塞,等待;
nio是线程非阻塞,其使用的buffer和channel(双向通道),当前通道没有数据读取时,可以切换到另一个通道(数据的来源或目的地)中;
3、io是一个线程一个连接
nio使用selector选择器,响应式处理客户端的请求,一个线程可以解决多个连接的数据处理;



二.nio使用
在io上使用
1.nio文件读写
2.io与nio实现大文件复制的效率对比:https://blog.csdn.net/zhangcongyi420/article/details/103099441
3.nio实现文件上传下载:https://blog.51cto.com/u_14693305/5529441
4.BIO、NIO、AIO按行读取文件汇总:https://blog.csdn.net/judyjie/article/details/86608283

在socket上使用
5.java nio简单示例:实现客户端与服务器一问一答:https://blog.csdn.net/qq_37855749/article/details/116190818

三.例子
1.nio文件读写例子
    /**
	 * nio 使用缓冲区,非直接缓冲区读写文件
	 */
	public void test3() {
	    try (
	    		FileInputStream fis = new FileInputStream("1.jpg");
	    		FileOutputStream fos = new FileOutputStream("2.jpg");
	    		FileChannel fisChannel = fis.getChannel();
	    	    FileChannel fosChannel = fos.getChannel();
	    		){
	    	// 分配指定大小的缓冲区
	    	ByteBuffer buf = ByteBuffer.allocateDirect(1024);
	    	// 将通道中的数据存取缓冲区
	    	while (fisChannel.read(buf) != -1) {
	    		// 读取信息
	    		buf.flip();
	    		fosChannel.write(buf);
	    		buf.clear();
	    	}
	    } catch (FileNotFoundException e) {
	    	// TODO Auto-generated catch block
	    	e.printStackTrace();
	    } catch (IOException e) {
	    	// TODO Auto-generated catch block
	    	e.printStackTrace();
	    }
	}
	
	/**
	 * 使用nio读写文件 :使用直接缓冲区读写文件,速度快,不建议使用,占内存,适用于小文件
	 */
	public static void test4(String file) throws IOException {
		// 读模式
        FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
        // StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
        FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
        // 内存映射文件和ByteBuffer.allocateDirect(1024);直接获取缓冲区一模一样
        // 缓存区目前在物理内存中,直接缓冲区只有ByteBuffer支持
        MappedByteBuffer map = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
        MappedByteBuffer map2 = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());

        // 直接操作缓冲区
        byte[] bs = new byte[map.limit()];
        map.get(bs);
        map2.put(bs);
        
    }
	
	/**
     * 通道之间传输数据,直接缓冲区复制文件
     */
    public void test5() throws IOException {
         // 读模式
         FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
         // StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
         FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
         // 从哪到哪去
         inChannel.transferTo(0, inChannel.size(), outChannel);
         outChannel.transferFrom(inChannel, 0, inChannel.size());
         inChannel.close();
         outChannel.close();
    }
	
	/**
     * 分散与读取,将通道中的内容分散到缓冲区中
     */
    public void test6() throws Exception {
         // 分散读取
         RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");
         // 获取通道
         FileChannel channel = raf.getChannel();

         // 分配指定大小缓冲区
         ByteBuffer allocate = ByteBuffer.allocate(100);
         ByteBuffer allocate2 = ByteBuffer.allocate(1000);
         // 分散读取
         ByteBuffer[] bio = { allocate, allocate2 };
         channel.read(bio);
         for (ByteBuffer byteBuffer : bio) {
             // 改编读模式
             byteBuffer.flip();
         }
         // 将缓冲区转换为数组,从第0个转换到limit
         System.out.println(new String(bio[0].array(), 0, bio[0].limit()));
         System.out.println("======================");
         System.out.println(new String(bio[0].array(), 0, bio[1].limit()));

         // 聚集写入
         RandomAccessFile rsf = new RandomAccessFile("2.txt", "rw");
         FileChannel channel2 = rsf.getChannel();

         channel2.write(bio);
    }

    
	/**
	 * 使用nio读取文件所有内容
	 */
	public static String readByNIO(String file){
		StringBuffer result = new StringBuffer();
		//第一步 获取通道
		try (
				FileInputStream fis = new FileInputStream(file);
				FileChannel channel=fis.getChannel();
				){
			//文件内容的大小
			int size=(int) channel.size();
			//第二步 指定缓冲区
			ByteBuffer buffer=ByteBuffer.allocate(size);
			//第三步 将通道中的数据读取到缓冲区中
			while(channel.read(buffer)!=-1) {
				Buffer bf= buffer.flip();
				byte[] bt=buffer.array();
				result.append(new String(bt,0,bt.length));
				buffer.clear();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result.toString();
	}
	
	/**
	  * 利用NIO将内容输出到文件中
	  */
	public static void writeFileByNIO(String file){
	    try (
	    		FileOutputStream fos = new FileOutputStream(file);
	    		//第一步 获取一个通道
	    	    FileChannel fc = fos.getChannel();
	    	    
	    	){
	    	//第二步 定义缓冲区
	    	ByteBuffer buffer = ByteBuffer.allocate(10);
	    	for(int i=0; i<100; i++) {
	    		String aaa = new String("aaa"+i);
	    		byte[] bytes = aaa.getBytes();
	    		for(int m=0; m<bytes.length; m++) {
	    			buffer.put(bytes[m]);
	    			if(buffer.remaining()==0) {
	    				buffer.flip();
	    				//将内容写到缓冲区
	    				fc.write(buffer);
	    				//fos.flush();
	    				buffer.clear();
	    			}
	    		}
	    	}
	    } catch (FileNotFoundException e) {
	    	e.printStackTrace();
	    } catch (IOException e) {
	    	e.printStackTrace();
	    }
	 }


四.io实现socket
Java 网络编程 TCP 传输文件:https://zhuanlan.zhihu.com/p/79377902
改进:服务端多线程处理业务逻辑: Socket 流传输的实现 —— 基于TCP协议:https://zhuanlan.zhihu.com/p/33103147

五.nio实现socket 多线程
https://blog.csdn.net/yiguang_820/article/details/126245942?spm=1001.2014.3001.5501
io和nio使用最大区别在网络通信方面,io是同步阻塞,nio是同步非阻塞
例子:https://blog.csdn.net/dhrtyuhrthfgdhtgfh/article/details/90271123

六.springboot实现socket
io、nio、netty:https://blog.csdn.net/smltq/article/details/103534704

七.springboot整合netty实现socket
Netty检查连接断开的几种方法(只用过第三种方法):https://www.cnblogs.com/alan6/p/11715722.html

八.websocket
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
springboot+websocket:https://blog.csdn.net/qq_18432653/article/details/109579829
springboot+netty实现websocket:

九:netty
1.官网示例:https://github.com/YeautyYE/netty-websocket-spring-boot-starter/blob/master/README_zh.md
例子:https://blog.csdn.net/qq_27248637/article/details/102552840
2.websocket可实现聊天系统

问题:
1.websocket连接1分钟后自动断开的解决方法:https://blog.csdn.net/rockstreet/article/details/113826562
WebSocket的心跳重连机制:https://blog.csdn.net/qq_33922980/article/details/102646295

十.问题:
1.请问 TCP、Socket、Servlet 、Tomcat 是如何通信的?https://www.zhihu.com/question/399406330
Tomcat 约等于 HTTP服务器(socket连接器) + Servlet容器
2.socket和servlet
socket是应用层与运输层之间的接口,一次连接在客户端和服务器分别有一个socket和server Socket,HTTP 报文经过socket接口进入运输层。
(1)Socket是最底层的通信机制
(2)HTTP是Socket之上的封装层,例如 HttpClient 等。
(3)Servlet是Java 对 HTTP的封装层,目的是为了更好的处理HTTP请求(包括参数)和HTTP响应,毕竟HTTP就分为请求和响应两大部分。
(4)Tomcat是Servlet容器。Servlet必须运行在容器之上。
Tomcat 实现了网络编程,通过servlet处理HTTP报文,再通过socket接口通信。因此我们只需编写经过封装了的servlet程序,容器通过反射等实现通信。
3.那么再来说说Socket和Tomcat的关系:https://www.cnblogs.com/zhangrj9/p/11678048.html
4.阻塞和非阻塞、同步和异步:https://baike.baidu.com/item/%E9%98%BB%E5%A1%9E%E5%92%8C%E9%9D%9E%E9%98%BB%E5%A1%9E/23734057?fr=aladdin
看完此链接后,同步异步在于是否需要等待结果返回;阻塞非阻塞在于当前线程在结果未返回之前是否可以做其他事情。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值