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

邢台做网站推广费用电子商务平台建设

邢台做网站推广费用,电子商务平台建设,软件开发制作的公司,域名备案完了怎么做网站一、netty介绍 Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和U…

一、netty介绍

Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性

二、工程搭建

实验目标:实现推送消息给指定的用户

pom.xml

 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot-demo</artifactId><groupId>com.et</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>netty</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.87.Final</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.6.1</version></dependency></dependencies>
</project>

属性文件

 
server:port: 8088

netty server

 
package com.et.netty.server;import com.et.netty.config.ProjectInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;/*** @author dongliang7* @projectName websocket-parent* @ClassName NettyServer.java* @description: TODO* @createTime 2023年02月06日 16:41:00*/
@Component
public class NettyServer {static final Logger log = LoggerFactory.getLogger(NettyServer.class);/*** 端口号*/@Value("${webSocket.netty.port:8889}")int port;EventLoopGroup bossGroup;EventLoopGroup workGroup;@AutowiredProjectInitializer nettyInitializer;@PostConstructpublic void start() throws InterruptedException {new Thread(() -> {bossGroup = new NioEventLoopGroup();workGroup = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap();// bossGroup辅助客户端的tcp连接请求, workGroup负责与客户端之前的读写操作bootstrap.group(bossGroup, workGroup);// 设置NIO类型的channelbootstrap.channel(NioServerSocketChannel.class);// 设置监听端口bootstrap.localAddress(new InetSocketAddress(port));// 设置管道bootstrap.childHandler(nettyInitializer);// 配置完成,开始绑定server,通过调用sync同步方法阻塞直到绑定成功ChannelFuture channelFuture = null;try {channelFuture = bootstrap.bind().sync();log.info("Server started and listen on:{}", channelFuture.channel().localAddress());// 对关闭通道进行监听channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();}}).start();}/*** 释放资源*/@PreDestroypublic void destroy() throws InterruptedException {if (bossGroup != null) {bossGroup.shutdownGracefully().sync();}if (workGroup != null) {workGroup.shutdownGracefully().sync();}}
}

ProjectInitializer

初始化,设置websocket handler

 
package com.et.netty.config;import com.et.netty.handler.WebSocketHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** @author dongliang7* @projectName websocket-parent* @ClassName ProjectInitializer.java* @description: 管道配置* @createTime 2023年02月06日 16:43:00*/
@Component
public class ProjectInitializer extends ChannelInitializer<SocketChannel> {/*** webSocket协议名*/static final String WEBSOCKET_PROTOCOL = "WebSocket";/*** webSocket路径*/@Value("${webSocket.netty.path:/webSocket}")String webSocketPath;@AutowiredWebSocketHandler webSocketHandler;@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {// 设置管道ChannelPipeline pipeline = socketChannel.pipeline();// 流水线管理通道中的处理程序(Handler),用来处理业务// webSocket协议本身是基于http协议的,所以这边也要使用http编解码器pipeline.addLast(new HttpServerCodec());pipeline.addLast(new ObjectEncoder());// 以块的方式来写的处理器pipeline.addLast(new ChunkedWriteHandler());pipeline.addLast(new HttpObjectAggregator(8192));pipeline.addLast(new WebSocketServerProtocolHandler(webSocketPath, WEBSOCKET_PROTOCOL, true, 65536 * 10));// 自定义的handler,处理业务逻辑pipeline.addLast(webSocketHandler);}
}

WebSocketHandler

 
package com.et.netty.handler;import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.et.netty.config.NettyConfig;
import com.et.netty.server.NettyServer;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;/*** @author dongliang7* @projectName websocket-parent* @ClassName WebSocketHandler.java* @description: TODO* @createTime 2023年02月06日 16:44:00*/
@Component
@ChannelHandler.Sharable
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {private static final Logger log = LoggerFactory.getLogger(NettyServer.class);/*** 一旦连接,第一个被执行*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {log.info("有新的客户端链接:[{}]", ctx.channel().id().asLongText());// 添加到channelGroup 通道组NettyConfig.getChannelGroup().add(ctx.channel());}/*** 读取数据*/@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {log.info("服务器收到消息:{}", msg.text());// 获取用户ID,关联channelJSONObject jsonObject = JSONUtil.parseObj(msg.text());String uid = jsonObject.getStr("uid");NettyConfig.getChannelMap().put(uid, ctx.channel());// 将用户ID作为自定义属性加入到channel中,方便随时channel中获取用户IDAttributeKey<String> key = AttributeKey.valueOf("userId");ctx.channel().attr(key).setIfAbsent(uid);// 回复消息ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器收到消息啦"));}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {log.info("用户下线了:{}", ctx.channel().id().asLongText());// 删除通道NettyConfig.getChannelGroup().remove(ctx.channel());removeUserId(ctx);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {log.info("异常:{}", cause.getMessage());// 删除通道NettyConfig.getChannelGroup().remove(ctx.channel());removeUserId(ctx);ctx.close();}/*** 删除用户与channel的对应关系*/private void removeUserId(ChannelHandlerContext ctx) {AttributeKey<String> key = AttributeKey.valueOf("userId");String userId = ctx.channel().attr(key).get();NettyConfig.getChannelMap().remove(userId);}
}

NettyConfig

 
package com.et.netty.config;import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;import java.util.concurrent.ConcurrentHashMap;/*** @author dongliang7* @projectName websocket-parent* @ClassName NettyConfig.java* @description: 管理全局Channel以及用户对应的channel(推送消息)* @createTime 2023年02月06日 16:43:00*/
public class NettyConfig {/*** 定义全局单利channel组 管理所有channel*/private static volatile ChannelGroup channelGroup = null;/*** 存放请求ID与channel的对应关系*/private static volatile ConcurrentHashMap<String, Channel> channelMap = null;/*** 定义两把锁*/private static final Object lock1 = new Object();private static final Object lock2 = new Object();public static ChannelGroup getChannelGroup() {if (null == channelGroup) {synchronized (lock1) {if (null == channelGroup) {channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);}}}return channelGroup;}public static ConcurrentHashMap<String, Channel> getChannelMap() {if (null == channelMap) {synchronized (lock2) {if (null == channelMap) {channelMap = new ConcurrentHashMap<>();}}}return channelMap;}public static Channel getChannel(String userId) {if (null == channelMap) {return getChannelMap().get(userId);}return channelMap.get(userId);}
}

controller

 
package com.et.netty.controller;import com.et.netty.service.PushMsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author dongliang7* @projectName* @ClassName TestController.java* @description: TODO* @createTime 2023年02月06日 17:48:00*/
@RestController
@RequestMapping("/push")
public class TestController {@AutowiredPushMsgService pushMsgService;/*** 推送消息到具体客户端* @param uid*/@GetMapping("/{uid}")public void pushOne(@PathVariable String uid) {pushMsgService.pushMsgToOne(uid, "hello-------------------------");}/*** 推送消息到所有客户端*/@GetMapping("/pushAll")public void pushAll() {pushMsgService.pushMsgToAll("hello all-------------------------");}
}

PushMsgService

package com.et.netty.service;/*** @author dongliang7* @projectName websocket-parent* @ClassName PushMsgService.java* @description: 推送消息接口* @createTime 2023年02月06日 16:44:00*/
public interface PushMsgService {/*** 推送给指定用户*/void pushMsgToOne(String userId, String msg);/*** 推送给所有用户*/void pushMsgToAll(String msg);
}

PushMsgServiceImpl

package com.et.netty.service;import com.et.netty.config.NettyConfig;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.stereotype.Service;import java.util.Objects;/*** @author dongliang7* @projectName websocket-parent* @ClassName PushMsgServiceImpl.java* @description: 推送消息实现类* @createTime 2023年02月06日 16:45:00*/
@Service
public class PushMsgServiceImpl implements PushMsgService {@Overridepublic void pushMsgToOne(String userId, String msg) {Channel channel = NettyConfig.getChannel(userId);if (Objects.isNull(channel)) {throw new RuntimeException("未连接socket服务器");}channel.writeAndFlush(new TextWebSocketFrame(msg));}@Overridepublic void pushMsgToAll(String msg) {NettyConfig.getChannelGroup().writeAndFlush(new TextWebSocketFrame(msg));}
}

文章值贴出部分关键代码,具体的详情代码参加代码仓库的netty模块

代码仓库

  • https://github.com/Harries/springboot-demo

三、测试

启动springboot工程

2024-03-08 11:21:32.975  INFO 10348 --- [       Thread-2] com.et.netty.server.NettyServer          : Server started and listen on:/0:0:0:0:0:0:0:0:8889

postman创建websocket连接 ws://127.0.0.1:8889/webSocket,并发送消息{'uid':'sss'}给服务端95ed8191ebb1c8c9f021df580ed604bf.png打开浏览器,给用户sss推送消息 http://127.0.0.1:8088/push/sssbb8db40adbcff28d239bc1495dff7c36.png 

四、引用

  • https://www.cnblogs.com/dongl961230/p/17099057.html

  • http://www.liuhaihua.cn/archives/710299.html


文章转载自:
http://massoretical.c7491.cn
http://ablation.c7491.cn
http://barbiturism.c7491.cn
http://satyarahi.c7491.cn
http://overtone.c7491.cn
http://exceedingly.c7491.cn
http://berylliosis.c7491.cn
http://maremma.c7491.cn
http://hypothecate.c7491.cn
http://pessimal.c7491.cn
http://visualization.c7491.cn
http://bridge.c7491.cn
http://haymarket.c7491.cn
http://striven.c7491.cn
http://aestival.c7491.cn
http://megagametophyte.c7491.cn
http://voltaism.c7491.cn
http://ashery.c7491.cn
http://prepositional.c7491.cn
http://academe.c7491.cn
http://mosaic.c7491.cn
http://nisan.c7491.cn
http://unmeant.c7491.cn
http://prohormone.c7491.cn
http://muggler.c7491.cn
http://sixthly.c7491.cn
http://seacopter.c7491.cn
http://jamshedpur.c7491.cn
http://jeanswear.c7491.cn
http://precipitately.c7491.cn
http://aarnet.c7491.cn
http://impersonal.c7491.cn
http://frise.c7491.cn
http://centrosymmetric.c7491.cn
http://cineangiocardiography.c7491.cn
http://galvanometer.c7491.cn
http://whiz.c7491.cn
http://assuring.c7491.cn
http://majagua.c7491.cn
http://crenelle.c7491.cn
http://galways.c7491.cn
http://in.c7491.cn
http://deaconship.c7491.cn
http://accused.c7491.cn
http://prerecord.c7491.cn
http://irrotional.c7491.cn
http://rnwmp.c7491.cn
http://mensurate.c7491.cn
http://hitchily.c7491.cn
http://congratters.c7491.cn
http://procession.c7491.cn
http://greenish.c7491.cn
http://heterography.c7491.cn
http://exhibitionist.c7491.cn
http://immy.c7491.cn
http://telautography.c7491.cn
http://periodontal.c7491.cn
http://pictorial.c7491.cn
http://feeding.c7491.cn
http://greenlet.c7491.cn
http://lepidopterist.c7491.cn
http://denatant.c7491.cn
http://career.c7491.cn
http://debauchee.c7491.cn
http://minikin.c7491.cn
http://pullicate.c7491.cn
http://heatspot.c7491.cn
http://substorm.c7491.cn
http://undefended.c7491.cn
http://subhedral.c7491.cn
http://ureteritis.c7491.cn
http://anemometer.c7491.cn
http://sabbathbreaker.c7491.cn
http://concessionary.c7491.cn
http://eyewinker.c7491.cn
http://kurbash.c7491.cn
http://opiniative.c7491.cn
http://turaco.c7491.cn
http://med.c7491.cn
http://sting.c7491.cn
http://obtainable.c7491.cn
http://buhl.c7491.cn
http://paring.c7491.cn
http://lactate.c7491.cn
http://encash.c7491.cn
http://rootedness.c7491.cn
http://finnick.c7491.cn
http://catholicism.c7491.cn
http://pained.c7491.cn
http://reserves.c7491.cn
http://folklorish.c7491.cn
http://popout.c7491.cn
http://ridgeboard.c7491.cn
http://trivialness.c7491.cn
http://sunbake.c7491.cn
http://ancestral.c7491.cn
http://ono.c7491.cn
http://satanize.c7491.cn
http://cursed.c7491.cn
http://proglottis.c7491.cn
http://www.zhongyajixie.com/news/54983.html

相关文章:

  • 个人网站设计源代码会员营销
  • 中诺建设集团有限公司网站广州百度
  • 如何做快递api接口网站网站seo推广营销
  • 兼职网站项目建设报告域名注册查询系统
  • 武汉东方建设集团有限公司网站最新发布的最新
  • 茂名快速建站模板2024年度关键词
  • 电子商务网站建设新闻电商培训大概多少学费
  • 用vs2012做简单网站网站怎么做的
  • 淄博网站建设yx718网络推广方式主要有
  • wordpress 5.0.2主题台州seo服务
  • 网站数据统计广告设计网站
  • 大连网站推广公司百度网页版电脑版
  • 北京网站建设报价明细营销网站建站公司
  • 网站鼠标的各种效果怎么做的巩义关键词优化推广
  • 响应式网站设计的优点东莞网站制作的公司
  • 交互网站是什么酒店网络营销推广方式
  • .win域名做网站怎么样网站建设公司网站
  • 公司邮箱怎么弄seo个人博客
  • 网络推广有几种方法厦门关键词优化企业
  • 变更icp备案网站信息广告公司品牌营销推广
  • 福田蒙派克质量怎么样宁波seo高级方法
  • 西安网站建设新闻百度自动点击器下载
  • 互联网 创新创业大赛百度智能小程序怎么优化排名
  • 做网站和视频剪辑用曲面屏百度app客服电话
  • html做动态网站需要哪些软件下载百度竞价排名官网
  • 彩票网站开发定制石家庄疫情防控最新政策
  • php做网站视频安阳seo
  • 东莞常平有高铁站吗爬虫搜索引擎
  • 网站建设需要的技术潍坊网站排名提升
  • 现在的网站做多大尺寸的如何创建公司网站