请教一个netty搭建websocket遇到的问题

qq_38588922 2019-06-17 03:05:50
我想实现一个功能,就是用netty搭建websocket,然后连接成功以后服务器端发一条数据给客户端,可是我连接成功以后 客户端并没有收到服务端的数据,只有客户端发送消息过来的时候,服务器才能返回一个消息过去,大佬们可以指点一下吗

@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg)
throws Exception {

// 获取客户端传输过来的消息
String content = msg.text();
System.out.println("接受到的数据:" + content);

for (Channel channel: clients) {
channel.writeAndFlush(
new TextWebSocketFrame(
"[服务器在]" + LocalDateTime.now()
+ "接受到消息, 消息为:" + content));
}
// 下面这个方法,和上面的for循环,一致
/*clients.writeAndFlush(
new TextWebSocketFrame(
"[服务器在]" + LocalDateTime.now()
+ "接受到消息, 消息为:" + content));*/

}
/**
* 客户端连接到服务端后进行
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端传给服务端");
String string = "116.478935,39.997761";
// ByteBuf buf = Unpooled.buffer(string.length());
// buf.retain();
// buf.writeBytes(string.getBytes());
// ctx.writeAndFlush(buf);
//
// System.out.println(ctx.writeAndFlush(b\
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
System.out.println("123");
}
...全文
347 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
smessi10 2021-08-02
  • 打赏
  • 举报
回复

你好,请问你是怎么解决的?我也遇到相同的问题了

jsudavid 2020-08-11
  • 打赏
  • 举报
回复
大佬 在channelActive中返回数据失败 但是延迟发送成功是可以的,为啥呀
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 13 楼 maradona1984 的回复:
[quote=引用 11 楼 qq_38588922 的回复:]
[quote=引用 10 楼 maradona1984 的回复:]
[quote=引用 9 楼 qq_38588922 的回复:]
[quote=引用 8 楼 maradona1984 的回复:]
websocket连接后,应该不会发送TextWebSocketFrame给服务端,你要在连上之后马上响应,直接在处理连接的代码里写不就行了吗?

/**
* 当客户端连接服务端之后(打开连接)
* 获取客户端的channle,并且放到ChannelGroup中去进行管理
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
String string = "116.478935,39.997761";
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
clients.add(ctx.channel());
}

处理连接的地方我也写了一个,还是没有用[/quote]
我建议你写在你handler里的userEventTriggered方法里,判断握手是否完成,握手完成直接响应,还有建议把netty版本号带上,几个版本的差异比较大,毕竟handlerAdded并不代表握手成功

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof HandshakeComplete) {
// 握手已完成,不需要再解析Http request了
ctx.pipeline().remove(HttpRequestHandler.class);
} else if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state().equals(IdleState.READER_IDLE)) {
ctx.close();
}
} else {
super.userEventTriggered(ctx, evt);
}
}
[/quote]

netty版本号为4.1.25.Final,首先感谢大佬的回复,然后HandshakeComplete,HttpRequestHandler这两个我引不到包。。[/quote]
代码只是例子罢了,HttpRequestHandler是我们的处理类,你肯定没有,HandshakeComplete看你的pom.xml是怎么写的,如果不是依赖的netty-all的话,那就单独依赖netty-codec-http这个模块,我这4.1.9和4.1.36都有这个类,不存在中间版本会没有这个类的[/quote]

感谢大佬 我的问题解决了!谢谢
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 12 楼 maradona1984 的回复:
当然还是得看你代码怎么写的,如果你用WebSocketServerProtocolHandshakeHandler来处理websocket连接断开相关与业务无关的协议,用我这个没错,如果你自己写代码触发握手,那你把握手后再响应消息吧

握手已经成功了的,我的另一个方法 服务端与客户端互发消息已经实现了,但是我想在此之前,服务器主动发一条消息给客户端,就是这个场景:后台给前台一个起点与终点,前台接收到,然后根据起点与终点形成一个线路,每秒返回一次当前坐标给后台,现在我前台的数据可以返回过去,但是我后台想给前台一个起点与终点的坐标,是希望在页面刚加载完成的时候就收到的一个数据
maradona1984 2019-06-17
  • 打赏
  • 举报
回复
引用 11 楼 qq_38588922 的回复:
[quote=引用 10 楼 maradona1984 的回复:] [quote=引用 9 楼 qq_38588922 的回复:] [quote=引用 8 楼 maradona1984 的回复:] websocket连接后,应该不会发送TextWebSocketFrame给服务端,你要在连上之后马上响应,直接在处理连接的代码里写不就行了吗?
/** * 当客户端连接服务端之后(打开连接) * 获取客户端的channle,并且放到ChannelGroup中去进行管理 */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { String string = "116.478935,39.997761"; ctx.channel().writeAndFlush(new TextWebSocketFrame(string)); clients.add(ctx.channel()); } 处理连接的地方我也写了一个,还是没有用[/quote] 我建议你写在你handler里的userEventTriggered方法里,判断握手是否完成,握手完成直接响应,还有建议把netty版本号带上,几个版本的差异比较大,毕竟handlerAdded并不代表握手成功

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof HandshakeComplete) {
			// 握手已完成,不需要再解析Http request了
			ctx.pipeline().remove(HttpRequestHandler.class);
		} else if (evt instanceof IdleStateEvent) {
			IdleStateEvent event = (IdleStateEvent) evt;
			if (event.state().equals(IdleState.READER_IDLE)) {
				ctx.close();
			}
		} else {
			super.userEventTriggered(ctx, evt);
		}
	}
[/quote] netty版本号为4.1.25.Final,首先感谢大佬的回复,然后HandshakeComplete,HttpRequestHandler这两个我引不到包。。[/quote] 代码只是例子罢了,HttpRequestHandler是我们的处理类,你肯定没有,HandshakeComplete看你的pom.xml是怎么写的,如果不是依赖的netty-all的话,那就单独依赖netty-codec-http这个模块,我这4.1.9和4.1.36都有这个类,不存在中间版本会没有这个类的
maradona1984 2019-06-17
  • 打赏
  • 举报
回复
当然还是得看你代码怎么写的,如果你用WebSocketServerProtocolHandshakeHandler来处理websocket连接断开相关与业务无关的协议,用我这个没错,如果你自己写代码触发握手,那你把握手后再响应消息吧
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 10 楼 maradona1984 的回复:
[quote=引用 9 楼 qq_38588922 的回复:]
[quote=引用 8 楼 maradona1984 的回复:]
websocket连接后,应该不会发送TextWebSocketFrame给服务端,你要在连上之后马上响应,直接在处理连接的代码里写不就行了吗?

/**
* 当客户端连接服务端之后(打开连接)
* 获取客户端的channle,并且放到ChannelGroup中去进行管理
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
String string = "116.478935,39.997761";
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
clients.add(ctx.channel());
}

处理连接的地方我也写了一个,还是没有用[/quote]
我建议你写在你handler里的userEventTriggered方法里,判断握手是否完成,握手完成直接响应,还有建议把netty版本号带上,几个版本的差异比较大,毕竟handlerAdded并不代表握手成功

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof HandshakeComplete) {
// 握手已完成,不需要再解析Http request了
ctx.pipeline().remove(HttpRequestHandler.class);
} else if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state().equals(IdleState.READER_IDLE)) {
ctx.close();
}
} else {
super.userEventTriggered(ctx, evt);
}
}
[/quote]

netty版本号为4.1.25.Final,首先感谢大佬的回复,然后HandshakeComplete,HttpRequestHandler这两个我引不到包。。
maradona1984 2019-06-17
  • 打赏
  • 举报
回复
引用 9 楼 qq_38588922 的回复:
[quote=引用 8 楼 maradona1984 的回复:] websocket连接后,应该不会发送TextWebSocketFrame给服务端,你要在连上之后马上响应,直接在处理连接的代码里写不就行了吗?
/** * 当客户端连接服务端之后(打开连接) * 获取客户端的channle,并且放到ChannelGroup中去进行管理 */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { String string = "116.478935,39.997761"; ctx.channel().writeAndFlush(new TextWebSocketFrame(string)); clients.add(ctx.channel()); } 处理连接的地方我也写了一个,还是没有用[/quote] 我建议你写在你handler里的userEventTriggered方法里,判断握手是否完成,握手完成直接响应,还有建议把netty版本号带上,几个版本的差异比较大,毕竟handlerAdded并不代表握手成功

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof HandshakeComplete) {
			// 握手已完成,不需要再解析Http request了
			ctx.pipeline().remove(HttpRequestHandler.class);
		} else if (evt instanceof IdleStateEvent) {
			IdleStateEvent event = (IdleStateEvent) evt;
			if (event.state().equals(IdleState.READER_IDLE)) {
				ctx.close();
			}
		} else {
			super.userEventTriggered(ctx, evt);
		}
	}
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 8 楼 maradona1984 的回复:
websocket连接后,应该不会发送TextWebSocketFrame给服务端,你要在连上之后马上响应,直接在处理连接的代码里写不就行了吗?

/**
* 当客户端连接服务端之后(打开连接)
* 获取客户端的channle,并且放到ChannelGroup中去进行管理
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
String string = "116.478935,39.997761";
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
clients.add(ctx.channel());
}

处理连接的地方我也写了一个,还是没有用
maradona1984 2019-06-17
  • 打赏
  • 举报
回复
websocket连接后,应该不会发送TextWebSocketFrame给服务端,你要在连上之后马上响应,直接在处理连接的代码里写不就行了吗?
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 6 楼 咸哼酒家 的回复:
[quote=引用 5 楼 qq_38588922 的回复:]
[quote=引用 3 楼 咸哼酒家 的回复:]
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
这段代码执行了但是没有真的发送成功,看看你发送的数据是什么,符不符合发送的格式要求,

String string = "116.478935,39.997761"; 数据是这个 String格式[/quote]

new TextWebSocketFrame(string) 这个内容是什么? 看看你已经发送正常的数据格式是什么,我记得netty默认的判断字符串结束要有
\n\r什么的[/quote]
// 获取客户端传输过来的消息
String content = msg.text();
System.out.println("接受到的数据:" + content);

for (Channel channel: clients) {
channel.writeAndFlush(
new TextWebSocketFrame(
"[服务器在]" + LocalDateTime.now()
+ "接受到消息, 消息为:" + content));
}

这一段是成功发送的代码
咸哼酒家 2019-06-17
  • 打赏
  • 举报
回复
引用 5 楼 qq_38588922 的回复:
[quote=引用 3 楼 咸哼酒家 的回复:]
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
这段代码执行了但是没有真的发送成功,看看你发送的数据是什么,符不符合发送的格式要求,

String string = "116.478935,39.997761"; 数据是这个 String格式[/quote]

new TextWebSocketFrame(string) 这个内容是什么? 看看你已经发送正常的数据格式是什么,我记得netty默认的判断字符串结束要有
\n\r什么的
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 3 楼 咸哼酒家 的回复:
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
这段代码执行了但是没有真的发送成功,看看你发送的数据是什么,符不符合发送的格式要求,

String string = "116.478935,39.997761"; 数据是这个 String格式
咸哼酒家 2019-06-17
  • 打赏
  • 举报
回复
可以用 异步的方式去调用,比如用这个注解@Async()
咸哼酒家 2019-06-17
  • 打赏
  • 举报
回复
ctx.channel().writeAndFlush(new TextWebSocketFrame(string));
这段代码执行了但是没有真的发送成功,看看你发送的数据是什么,符不符合发送的格式要求,
qq_38588922 2019-06-17
  • 打赏
  • 举报
回复
引用 1 楼 咸哼酒家 的回复:
ctx.channel().writeAndFlush(发送内容);
这是发送的代码,将收到连接ctx或者 ctx.channel()存入内存中,比如:
存入map,map.put("一个客户端key",ctx.channel())
想给任何一个客户端发送,获取到这个key,从map中拿到ctx.channel(),然后执行发送的代码


目前情况是这样的,就是我服务器端主动发一条数据给客户端,客户端是有返回信息的,但是我加了一个方法,希望客户端能够在连接成功的第一时间就发送一条消息给服务端,然后不断接收到服务端返回过来的消息,但是我在连接成功的方法里面写了ctx.channel().writeAndFlush(new TextWebSocketFrame(string)); 在客户端却并没有收到信息,并且在控制台打印了123,说明这个方法是成功进入了的,想请教一下这个方法是否能够通过开一条新线程的方法解决,如果可以的话,能否请教一下netty里如何开一条新的线程。。因为我是刚接触java 有些地方不太明白
咸哼酒家 2019-06-17
  • 打赏
  • 举报
回复
ctx.channel().writeAndFlush(发送内容);
这是发送的代码,将收到连接ctx或者 ctx.channel()存入内存中,比如:
存入map,map.put("一个客户端key",ctx.channel())
想给任何一个客户端发送,获取到这个key,从map中拿到ctx.channel(),然后执行发送的代码
   本课程由《Netty 4核心原理作者》亲授。    在互联网分布式系统的推动下,Netty 作为一个能够支撑高性能、高并发的底层网络通信框架而存在。Netty 底层是基于 Java NIO 实现的,对 NIO 进行了非常多的优化,因此深受广大开发者尤其是一线大厂开发者的青睐。    作为一个 Java 开发者,如果没有研究过 Netty,那么你对 Java 语言的使用和理解可能仅仅停留在表面,会点 SSH,写几个 MVC,访问数据库和缓存,这些只是初级 Java 开发者做的事。如果你要进阶,想了解 Java 服务器的高阶知识,Netty一个必须要跨越的门槛。学会了 Netty,你可以实现自己的 HTTP 服务器、FTP 服务器、UDP 服务器、RPC 服务器、WebSocket 服务器、Redis 的 Proxy 服务器、MySQL 的 Proxy 服务器等。    如果你想知道 Nginx 是怎么写出来的,    如果你想知道 Tomcat 和 Jetty 是如何实现的,    如果你也想实现一个简单的 Redis 服务器,    ……    那么你应该好好研究一下 Netty,它们高性能的原理都是类似的。    因为 Netty 5.x 已被官方弃用,本课程内容基于 Netty 4 分析其核心原理,培养高级开发者自己“造轮子”的能力。本课程不仅讲述理论知识,还围绕能够落地的实战场景,开创手写源码的学习方式,使学习源码更加高效。本书的主要特色是首次提供了基于 Netty 手写 RPC 框架、基于 Netty 手写消息推送系统等实战案例。

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧