LLLLLuuusa的个人博客 - 网络通信
type: channel
link: https://www.llllluuusa.top/index.php/tag/%E7%BD%91%E7%BB%9C%E9%80%9A%E4%BF%A1/
items: websocket
items: Netty

websocket
type: item
date: 2025-07-18T21:37:08+08:00
description: 介绍websocket是一种网络通信协议.RFC6455定义了它的通信标准websocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议.对比HTTPHTTP协议是一种无状态的、无连接的、单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理.这种通信模型有一个弊端.HTTP协议无法实现服务器主动向客户端发起消息这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦.大多数Web应用程序通过频繁的异步AJAX请求实现长轮询.轮询的效率低,非常浪费资源(因为必须不停连接,或者HTTP连接始终的打开)http协议:websocket协议:协议规则websocket协议由两部分组成:握手和数据交互来自客户端的握手请求头如下:http GET ws://localhost/chat HTTP/1.1 Host: localhost Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGHlIHNhbXBsZsbub25jZQ== Sec-WebSocket-Extensions:permessage-defalte Sec-WebSocket-version: 13来自服务器的握手看起来像如下形式:html HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: s3pPLMBiTxaQ9kYGzzhZRbk+xOo= Sec-WebSocket-Extensions:permessage-defalte| 头名称 | 说明 | | ------------------------- | ---------------------------------------------------------- | | Connection: Upgrade | 表示该HTTP请求是一个协议升级请求 | | Upgrade: websocket | 协议升级为WebSocket的版本 | | Sec-WebSocket-version: 13 | 客户端支持WebSocket的版本 | | Sec-WebSocket-Key | base64编码的24位随机字符,表示本次请求客户端/服务端的唯一Id | | Sec-WebSocket-Extensions | 协议拓展类型 |客户端实现websocket对象http5支持使用websocket以下API用于创建websocket对象:js //url格式: ws//ip地址:端口号/路径 var ws = new WebSocket(url);websocket事件websocket对象的相关事件| 事件 | 事件处理程序 | 描述 | | ------- | --------------------- | -------------------------- | | open | websocket对象.onopen | 连接建立时触发 | | message | websocket对象.onopen | 客户端接收服务端数据时触发 | | error | websocket对象.onerror | 通信发生错误时触发 | | close | websocket对象.onclose | 连接关闭时触发 |websocket方法websocket相关方法| 方法 | 描述 | | ------ | ---------- | | send() | 发送消息\| |服务端spring实现安装依赖xml <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency>方法和事件Tomcat7版本开始支持websocket,并实现了Java WebSocket规范Java WebSocket应用由一系列的WebSocketEndpoint组成.Endpoint是一个java对象,代表websocket连接的一段,对于服务端,我们可以视为处理具体websocket消息的接口,就像servlet之与http请求一样我们可以通过两种方式定义Endpoint: 第一种是编程式,即继承类javax.websocket.Endpoint并实现其方法 第二种是注解式,即定义一个POJO,并添加@ServerEndpoint相关注解 Endpoin…

Netty
type: item
date: 2025-07-18T21:37:08+08:00
description: 介绍分布式开发基于网络编程,网络编程主要使用netty进行开发,如果不想只是增删改查,而是开发自己的分布式架构,就需要使用nettyNIO编程NIO:非阻塞IO三大组件-ChannelChannel:双向通道,即可输出也可输入.以前学的InputStream只能输入,OutputStream只能输出Buffer:内存缓冲,暂存Channel的数据常见的Channel有: FileChannel DatagramChannel SocketChannel ServerSocketChannel FileChannel模式FileChannel只能在阻塞模式下使用,且不能直接使用FileInputStream、FileOutputStream、RandomAccessFile来获取Channel,它们都有getChannel方法 FileInputSteam获取的channel只能读 FileOutputSteam获取的channel只能写 RandomAccessFile根据读写模式决定读写 FileChannel常见方法java //关闭 channel.close(); //写入 channel.write(buf); //传输,两个channel传输数据,效率高,会利用操作系统底层优化 channel1.transferTo(int 起始,int 末位,channel2)三大组件-Buffer常见的Buffer: ByteBufer MappedByteBuffer DirectByteBuffer HeapByteBuffter ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffter CharBuffter ByteBuffter结构ByteBuffter常见方法java //分配空间,父类HeapBuffter,使用堆内存,读写慢,受GC(垃圾回收)影响 ByteBuffter buf = ByteBuffter.allocate(int); //分配空间,父类DirectBuffter,使用系统内存,分配慢 ByteBuffter buf = ByteBuffter.allocate(int); //获取长度 buf.capacity();java //切换模式,读/写 buf.flip();java //存入Buffter的数据,写入数据,有两种方法 //1.调用channel的read方法 int readBytes = channel.read(buf); //2.调用Buffter自身的put方法 buf.put(byte(127));java //取出Buffter的数据,读取数据,有两种方法 //1.调用channel的write方法 int writeBytes = channel.write(buf); //2.调用Buffter自身的get方法 byte b = buf.get(); byte b = buf.get(byte[])//将读取的数据存入byte数组 //2.1 get方法会让指针向后走,如果不希望指针移动可以: buf.rewind();//索引归0 byte b = buf.get(int 索引);//获取具体索引 //2.2 和rewind类似的方法有mark和reset buf.mark();//标记当前索引 buf.reset;//索引回到标记java //字符串转buffter,有三种方法 //1.最原始方法,字符串转字节数组,再存入buffter ByteBuffter buf = ByteBuffter.put("最原始方法".getBytes()); //2.Charset指定编码格式方法,自动切换读模式 ByteBuffter buf = StandardCharsets.UTF_8.encode("转码方式"); //3.直接转化方式,自动切换读模式 ByteBuffter buf = ByteBuffter.wrap("直接转化".getBytes())java //buffter转字符串 String str = StandardCharsets.UTF_8.decode(buffter).toString;三大组件-Selector传统的聊天通讯架构是使用多线程:多线程的缺点: 内存占用高 线程上下文切换成本高 只适合连接数少的场景 有一种优化分案就是使用线程池:线程池的缺点: 阻塞模式下,只能处理一个socket 仅适合短连接场景 而selector的思路就是一个线程管理多个channel,获取channel发生的事件,非阻塞模式下,不会让线程吊死在一个channel上,适合连接数多,但流量低的…