社区
Java SE
帖子详情
netty服务端如何向客户端发送消息
qq_36865470
2018-09-06 08:32:39
问题描述:
希望通过管理后台控制客户端的行为,比如:升级、断电等。通讯框架采用Netty,现在遇见的问题是 服务器端(即管理后台)怎么向客户端发送消息(网上大部分说缓存客户端的Channel),但是项目的后台、前台、以及Netty Server都是分离的。 这个时候该怎么做呢?请大家给点意见!
...全文
2158
2
打赏
收藏
netty服务端如何向客户端发送消息
问题描述: 希望通过管理后台控制客户端的行为,比如:升级、断电等。通讯框架采用Netty,现在遇见的问题是 服务器端(即管理后台)怎么向客户端发送消息(网上大部分说缓存客户端的Channel),但是项目的后台、前台、以及Netty Server都是分离的。 这个时候该怎么做呢?请大家给点意见!
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
2 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
爱码叔
2018-09-24
打赏
举报
回复
netty server肯定持有和前台(客户端)连接的所有channel。所以你的后台要不搭在netty server上,要不然也作为一个特殊的客户端链接到netty server,netty server接到此客户端的消息后,转发(广播)给所有的客户端。
qq_35358818
2018-09-14
打赏
举报
回复
1.普通字符串消息传递
服务器端:
public void startServer(int port) throws InterruptedException{
EventLoopGroup work=new NioEventLoopGroup();
EventLoopGroup boss=new NioEventLoopGroup();
ServerBootstrap bootStrap=new ServerBootstrap();
bootStrap.group(boss, work);
bootStrap.channel(NioServerSocketChannel.class);
bootStrap.option(ChannelOption.SO_BACKLOG,1024);
bootStrap.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline=ch.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new ServerHandler());
}
});
//绑定端口,同步等待成功.
ChannelFuture future=bootStrap.bind(port).sync();
//等待服务端监听端口关闭
future.channel().closeFuture().sync();
boss.shutdownGracefully();
work.shutdownGracefully();
}
public class ServerHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
System.out.println("msg:"+msg);
/*ByteBuf buf=(ByteBuf)msg;
byte[] req=new byte[buf.readableBytes()];
buf.readBytes(req);
String body=new String(req,"UTF-8");
System.out.println("body:"+body);
ctx.pipeline().writeAndFlush(buf);*///手动解析收到的数据
ctx.pipeline().writeAndFlush("hi......");
}
}
客户端:
public void startClient(String host,int port) throws InterruptedException{
EventLoopGroup group=new NioEventLoopGroup();
Bootstrap bootStrap=new Bootstrap();
bootStrap.group(group);
bootStrap.channel(NioSocketChannel.class);
bootStrap.option(ChannelOption.SO_KEEPALIVE,true);
bootStrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
ChannelPipeline pipeline=sc.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new ClientHandler());
}
});
//绑定端口,同步等待成功.
ChannelFuture future=bootStrap.connect(host,port).sync();
future.channel().writeAndFlush("hello");
//等待服务端监听端口关闭
future.channel().closeFuture().sync();
group.shutdownGracefully();
}
public class ClientHandler extends ChannelHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
System.out.println("msg:"+msg);
}
}
2.对象类型消息传递(传递对象直接实现Serializable)
服务器端(与普通字符串不同的部分标红):
public void startServer(int port) throws InterruptedException{
EventLoopGroup work=new NioEventLoopGroup();
EventLoopGroup boss=new NioEventLoopGroup();
ServerBootstrap bootStrap=new ServerBootstrap();
bootStrap.group(boss, work);
bootStrap.channel(NioServerSocketChannel.class);
bootStrap.option(ChannelOption.SO_BACKLOG,1024);
bootStrap.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline=ch.pipeline();
pipeline.addLast(new ObjectEncoder());//将String类型转化为ByteBuf类型,解析发送出去的
pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader())));//将收到的ByteBuf转化为String类型,解析收到的
pipeline.addLast(new ServerHandler());
}
});
//绑定端口,同步等待成功.
ChannelFuture future=bootStrap.bind(port).sync();
//等待服务端监听端口关闭
future.channel().closeFuture().sync();
boss.shutdownGracefully();
work.shutdownGracefully();
}
ServerHandler处理器代码一样。
客户端:
public void startClient(String host,int port) throws InterruptedException{
EventLoopGroup group=new NioEventLoopGroup();
Bootstrap bootStrap=new Bootstrap();
bootStrap.group(group);
bootStrap.channel(NioSocketChannel.class);
bootStrap.option(ChannelOption.SO_KEEPALIVE,true);
bootStrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
ChannelPipeline pipeline=sc.pipeline();
pipeline.addLast(new ObjectEncoder());//将String类型转化为ByteBuf类型,解析发送出去的
pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader())));//将收到的ByteBuf转化为String类型,解析收到的
pipeline.addLast(new ClientHandler());
}
});
//绑定端口,同步等待成功.
ChannelFuture future=bootStrap.connect(host,port).sync();
Student student=new Student("user","psw");
future.channel().writeAndFlush(student);
//等待服务端监听端口关闭
future.channel().closeFuture().sync();
group.shutdownGracefully();
}
ClientHandler处理器代码一样。
对象Student(必须实现Serializable接口):
public class Student implements Serializable{
private String name;
private String psw;
public Student(String name,String psw){
this.name=name;
this.psw=psw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
@Override
public String toString() {
return "[name:"+name+";password:"+psw+"]";
}
}
2.对象类型消息传递(protostuff实现序列化)
服务端:
bootStrap.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline=ch.pipeline();
pipeline.addLast(new MyDecoder(Student.class));
pipeline.addLast(new MyEncoder(Student.class));
pipeline.addLast(new ServerHandler());
}
客户端:
bootStrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
ChannelPipeline pipeline=sc.pipeline();
pipeline.addLast(new MyDecoder(Student.class));
pipeline.addLast(new MyEncoder(Student.class));
pipeline.addLast(new ClientHandler());
传递对象:
public class Student{
private String name;
private String psw;
解码器:
public class MyDecoder extends ByteToMessageDecoder{
private Class<?> genericClass;
public MyDecoder(Class<?> genericClass) {
this.genericClass = genericClass;
}
@Override
public final void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> out) throws Exception {
int dataLength = buf.readInt();//这边读取的第一个是长度字段
byte[] data = new byte[dataLength];
buf.readBytes(data);//将in中的数据写入data
Object obj = ProtoStuffUtil.deserialize(data, genericClass);
out.add(obj);
}
}
编码器:
public class MyEncoder extends MessageToByteEncoder{
private Class<?> genericClass;
public MyEncoder(Class<?> genericClass) {
this.genericClass = genericClass;
}
@Override
public void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) throws Exception {
if (genericClass.isInstance(in)) {
byte[] data = ProtoStuffUtil.serialize(in);
out.writeInt(data.length);//这边设置的第一个是长度字段
out.writeBytes(data);
}
}
}
序列化工具类:
public class ProtoStuffUtil {
private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
//对象转字节数组序列化
public static <T> byte[] serialize(T obj) {
Class<T> cls = (Class<T>) obj.getClass();//获取对象的类
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);//使用LinkedBuffer分配一块默认大小的buffer空间
try {
Schema<T> schema = getSchema(cls);//通过对象的类构建对象的schema
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);//使用给定的schema将对象序列化为一个byte数组,并返回
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
//字节数组转对象反序列化
public static <T> T deserialize(byte[] data, Class<T> cls) {
try {
T message = cls.newInstance();
Schema<T> schema = getSchema(cls);
ProtostuffIOUtil.mergeFrom(data, message, schema);//使用给定的schema将byte数组和对象合并
return message;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
if (schema != null) {
cachedSchema.put(cls, schema);
}
}
return schema;
}
}
netty
文件传输
服务端
与
客户端
以及协议说明
通过
netty
编写文件传输的
客户端
与
服务端
,以及协议说明, 通用的
netty
传输协议 通过该协议进行文件传输 文件传输
客户端
与
服务端
可以根据文件的最后更新时间来增量传输文件 源码开放,通过eclipse或者idea导入代码即可运行 协议开放,协议是自定义的协议,大家可以根据需求自行修改 具体详细协议请参考主页的《TCP通讯协议参考》 已经经过验证,传输效率高 仅供参考,勿喷
Netty
中使用WebSocket实现
服务端
与
客户端
的长连接通信
发送
消息
示例代码.rar
Netty
中使用WebSocket实现
服务端
与
客户端
的长连接通信
发送
消息
示例代码;
Netty
中使用WebSocket实现
服务端
与
客户端
的长连接通信
发送
消息
示例代码;
Netty
中使用WebSocket实现
服务端
与
客户端
的长连接通信
发送
消息
示例代码
Netty
实现Java
服务端
和C#
客户端
联通
实现Java
服务端
和C#
客户端
联通 Java使用
Netty
开发环境为IDEA C#使用Dot
Netty
开发环境为VS2017 运行时先开启Java
服务端
再开启
客户端
Netty
实现scoket 主动推送数据到服务和
服务端
实现方式
客户端
发送
16进制给
服务端
,并行实现socket通道活动状态和断开重新连接的功能, 监听接口是否存在数据,如果存在socket
客户端
发送
给socket
服务端
的实现 随着物联网的发展,随之出现了各种传感器监测数据的实时
发送
,需要和
netty
服务器通讯,
netty
和传感器之间需要保持长连接(换句话说,
netty
和gateway之间都会主动给对方
发送
消息
) 碰到的问题:
netty
作为服务器端如何主动的向传感器
发送
消息
,我尝试当每个传感器连接到
netty
(TCP/IP)时使用一个map把该channelSocket的id和该channelSocket绑定在一起。
物联网
netty
服务端
和
客户端
两个项目
物联网
Netty
服务端
,接收多设备
发送
协议报文,处理粘包;
客户端
监听
服务端
数据,保证
客户端
断联后进行重连,实现高可用
Java SE
62,614
社区成员
307,326
社区内容
发帖
与我相关
我的任务
Java SE
Java 2 Standard Edition
复制链接
扫一扫
分享
社区描述
Java 2 Standard Edition
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章