C#:使用DotNetty搭建的Socket服务器无法正常接收客户端消息?
实现DotNetty服务器接收并展示客户端字符串消息
看起来你已经在写测试客户端了,不过代码好像没写完,我先帮你补全并格式化客户端代码,然后给你对应的DotNetty服务器实现,确保能正确接收并展示消息。
补全后的客户端代码
using System; using System.Net; using System.Net.Sockets; using System.Text; class ClientProgram { static void Main(string[] args) { var ipAddress = "127.0.0.1"; var port = 1232; using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { socket.Connect(new IPEndPoint(IPAddress.Parse(ipAddress), port)); Console.WriteLine("已连接到服务器"); } catch (SocketException se) { Console.WriteLine($"连接服务器失败:{se.Message}"); return; } // 发送字符串消息 byte[] forwardMessage = Encoding.Default.GetBytes("lol"); socket.Send(forwardMessage); Console.WriteLine("消息已发送"); // 关闭连接 socket.Shutdown(SocketShutdown.Both); } }
DotNetty服务器实现代码
要让服务器正确解析客户端发送的字符串,需要配置对应的字符串编解码器,同时自定义Handler来处理消息:
using DotNetty.Bootstrapping; using DotNetty.Handlers.Codec.String; using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Sockets; using System; using System.Text; using System.Threading.Tasks; class ServerProgram { static async Task Main(string[] args) { // 配置EventLoopGroup,bossGroup负责接收连接,workerGroup处理后续IO var bossGroup = new MultithreadEventLoopGroup(1); var workerGroup = new MultithreadEventLoopGroup(); try { var bootstrap = new ServerBootstrap(); bootstrap .Group(bossGroup, workerGroup) .Channel<TcpServerSocketChannel>() .Option(ChannelOption.SoBacklog, 100) .ChildHandler(new ActionChannelInitializer<IChannel>(channel => { var pipeline = channel.Pipeline; // 关键:添加字符串解码器,编码要和客户端一致(这里用Encoding.Default) pipeline.AddLast(new StringDecoder(Encoding.Default)); // 如果需要给客户端回复消息,添加字符串编码器 pipeline.AddLast(new StringEncoder(Encoding.Default)); // 添加自定义的消息处理Handler,用于打印收到的消息 pipeline.AddLast(new MessageDisplayHandler()); })); // 绑定端口启动服务器 var boundChannel = await bootstrap.BindAsync(IPAddress.Loopback, 1232); Console.WriteLine("DotNetty服务器已启动,等待客户端连接..."); await boundChannel.CloseCompletion; } finally { // 优雅关闭资源,避免内存泄漏 await Task.WhenAll( bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); } } } // 自定义Handler,负责接收并展示客户端消息 public class MessageDisplayHandler : SimpleChannelInboundHandler<string> { // 收到客户端消息时触发 protected override void ChannelRead0(IChannelHandlerContext context, string message) { Console.WriteLine($"收到客户端[{context.Channel.RemoteAddress}]的消息:{message}"); // 如果需要回复客户端,取消下面注释即可 // await context.WriteAndFlushAsync($"服务器已收到消息:{message}"); } // 客户端连接成功时的回调 public override void ChannelActive(IChannelHandlerContext context) { Console.WriteLine($"客户端[{context.Channel.RemoteAddress}]已连接"); base.ChannelActive(context); } // 客户端断开连接时的回调 public override void ChannelInactive(IChannelHandlerContext context) { Console.WriteLine($"客户端[{context.Channel.RemoteAddress}]已断开连接"); base.ChannelInactive(context); } // 处理异常情况 public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) { Console.WriteLine($"服务器发生异常:{exception.Message}"); _ = context.CloseAsync(); } }
关键注意事项
- 编码一致性:客户端用
Encoding.Default将字符串转字节,服务器的StringDecoder必须使用相同的编码,否则会出现乱码问题 - 资源释放:服务器的
MultithreadEventLoopGroup一定要在最后优雅关闭,否则会造成资源泄漏 - 客户端异常处理:原代码的catch块是空的,建议添加错误日志,方便排查连接失败的原因
- 连接关闭:客户端发送完消息后要调用
Shutdown关闭连接,否则服务器可能会一直等待客户端发送更多数据
内容的提问来源于stack exchange,提问作者user5405648
相关产品推荐
相关产品推荐

