dotnetty使用过程中遇到的问题记录
【摘要】 以启动服务端为例,dotnetty在管道中会配置简单的解码,如果需要分包发送数据,或者一些复杂的发送数据场景中,可以在管道中配置IChannelHandler类,具体分几类可以在网上查相关资料,以代码为例,LengthFieldPrepender中的4代表发送的数据中前4个字节表示为数据长度,后续的才是实际要用到的数据,在自定义的EchoServerHandler方法的ChannelRead...
以启动服务端为例,dotnetty在管道中会配置简单的解码,如果需要分包发送数据,或者一些复杂的发送数据场景中,可以在管道中配置IChannelHandler类,具体分几类可以在网上查相关资料,以代码为例,LengthFieldPrepender中的4代表发送的数据中前4个字节表示为数据长度,后续的才是实际要用到的数据,在自定义的EchoServerHandler方法的ChannelRead方法中的message变量,会体现出来获取到的实际字节。如果这里配置的数据出错就会产生粘包,排查发送及接收的配置即可。
/// <summary>
/// 启动服务端
/// </summary>
/// <returns></returns>
public static async Task RunServerAsync(int port, int type)
{
IEventLoopGroup mainGroup;
IEventLoopGroup workerGroup;
mainGroup = new MultithreadEventLoopGroup(1);
workerGroup = new MultithreadEventLoopGroup();
var bootstrap = new ServerBootstrap();
try
{
bootstrap.Group(mainGroup, workerGroup);
bootstrap.Channel<TcpServerSocketChannel>();
bootstrap.Option(ChannelOption.SoBacklog, 100)
.Handler(new LoggingHandler("DotNetty-LSTN"))
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler("DotNetty-CONN"));
//pipeline.AddLast("DotNetty-enc", new LengthFieldPrepender(4));
//pipeline.AddLast("DotNetty-dec", new LengthFieldBasedFrameDecoder(int.MaxValue, 0, 4, 0, 4));
pipeline.AddLast("echo", new EchoServerHandler(type));
}));
IChannel clientchannel = await bootstrap.BindAsync(port).ConfigureAwait(true);
MainWindow.EPrintLog("开始监听端口" + port);
//// 关闭服务
//await clientchannel.CloseAsync().ConfigureAwait(true);
}
catch (Exception ex)
{
MainWindow.EPrintLog(ex.ToString());
await Task.WhenAll(
mainGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1)),
workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1))).ConfigureAwait(false);
}
//finally
//{
// await Task.WhenAll(
// mainGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1)),
// workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1))).ConfigureAwait(false);
//}
}
dotnetty解码器其中有一种是自定义长度,关键字是LengthFieldPrepender,但是虽然说叫自定义长度,但是只支持数据报文长度占1,2,3,4,8个字节这几种长度,项目中偏偏是定义了前6位字节为报文长度,搞得人很被动,只能自己解码了,其中遇到了这样一个问题:
A请求数据长度为1400字节,分了两次发送,第一次发送了1024字节,第二次376字节。在第一次发送成功后,netty等 待数据时,B请求进行了数据发送,长度是200字节,此时暂存得byte数据成了1224字节,变量数据混乱。经查询有一种 线程本地变量,代码如下:
private ThreadLocal<byte[]> clientBytes = new ThreadLocal<byte[]>(() => Array.Empty<byte>(), true);
ThreadLocal中第二个布尔值代表了是否可以在线程外操作该变量,数据操作通过value字段进行,示例如下:
clientBytes.Value = clientBytes.Value.Concat(tempbytes).ToArray();
3.log4net配置的问题,因为调用的外部dll文件里的方法本身也配置了log4net,主程序在调用dll文件时每调用一次都会cretateRepository,导致重复多次调用时会报错,提示已存在该repositoryName,目前解决办法是不在dll插件里调用cretateRepository方法,但是会造成与主程序过多的耦合。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)