Helios是一套高性能的Socket通信中间件,使用C#编写。Helios的开发受到Netty的启发,使用非阻塞的事件驱动模型架构来实现高并发高吞吐量。Helios为我们大大的简化了Socket编程,它已经为我们处理好了高并发情况下的解包,粘包,buffer管理等等。
GitHub:https://github.com/helios-io/helios/
为避免误会特别提示:helios不是本人作品,小弟还在努力的路上。
二:Helios的特点 1.Powerful APIsTakes the complexity out of socket programming with intelligent I/O, concurrency, buffer management, and pipelining APIs.
使用socket编程不再复杂。提供智能的I/O,并发,buffer管理,管道形式的API。
2.Event-DrivenHelios is Reactive - it uses a event-driven architecture to simplify development and build responsive systems that scale.
Helios是反应式的,它使用事件驱动的架构来简化开发和构建易伸缩的系统。
3.PerformantPerformance is a cross-cutting concern we factor in at every level in the design of the framework in order to eliminate overhead for your apps and clients.
这个系统在开发和设计的时候都充分考虑到了性能,构建你的app和client的时候请消除这方面的顾虑。
4.Battle-TestedHelios powers the clustering and remoting capbilities built into Akka.NET and more.
Akka.net的集群,远程功能构建在Helios之上。
三:一个基于Helios的聊天室示例要用来演示Socket通信那么最好的示例无非就是聊天程序了。
整个解决方案包含3个项目:
1.HeliosChat.Common
这个项目里是一些公共的类型,新建完之后使用nuget添加helios的库
Message 类:所有发送的消息都是通过Message包装的,每一个消息都有一个Command跟Content来构成。
public class Message { public Command Command { get; set; } public string Content { get; set; } }
Command枚举:用来描述消息的命令
public enum Command { Join, Send, }
MessageConverter静态类:这个类用来转换Message对象为Byte[],或者把Byte[]转换成Message对象。Message对象在通过Helios传输的时候需要先转成Byte[],所以我们需要自己定义包的格式。我们用Byte[]的前四位来存放Command,Content转成Byte后从第5位开始存放。
public class MessageConverter { public static Message ToMessage(NetworkData data) { try { var commandData = data.Buffer.Take(4).ToArray(); var contentData = data.Buffer.Skip(4).Take(data.Buffer.Length - 4).ToArray(); var command = BitConverter.ToInt32(commandData,0); var content = Encoding.UTF8.GetString(contentData); return new Message() { Command = (Command)command, Content = content }; } catch (Exception exc) { Console.WriteLine(, exc.Message); } return null; } [] ToBytes(Message message) { try { var commandBytes = BitConverter.GetBytes((int)message.Command); var messageBytes = Encoding.UTF8.GetBytes(message.Content); var bytes = new byte[commandBytes.Length + messageBytes.Length]; commandBytes.CopyTo(bytes, 0); messageBytes.CopyTo(bytes, commandBytes.Length); return bytes; } catch (Exception exc) { Console.WriteLine(, exc.Message); } return null; } }
2.HeliosChat.Server不用说也知道,这是聊天室的服务端,负责连接用户及转发消息。
internal class Program { ConcurrentDictionary<string, IConnection> Clients = new ConcurrentDictionary<string, IConnection>(); Main(string[] args) { var host = IPAddress.Any; var port = 9991; Console.Title = ; Console.WriteLine(, host, port); var serverFactory = new ServerBootstrap() .SetTransport(TransportType.Tcp) .Build(); var server = serverFactory.NewReactor(NodeBuilder.BuildNode().Host(host).WithPort(port)); server.OnConnection += (address, connection) => { Console.WriteLine(, address); connection.BeginReceive(Receive); }; server.OnDisconnection += (reason, address) => Console.WriteLine(, address.RemoteHost, reason.Type); server.Start(); Console.WriteLine(); Console.ReadKey(); } 处理接受到的消息 Receive(NetworkData data, IConnection channel) { var message = MessageConverter.ToMessage(data); switch (message.Command) { case Command.Join: JoinGroup(message.Content, channel); break; case Command.Send: Broadcast(message.Content); break; } } JoinGroup(string clientName, IConnection channel) { if (Clients.TryAdd(clientName, channel)) { Broadcast(, clientName)); } else { var errMsg = new Message() { Command = Command.Send, Content = }; SendMessage(channel, errMsg); } } 广播消息 Broadcast(string clientMessage) { Console.WriteLine(clientMessage); )[0]; var message = new Message { Command = Command.Send, Content = clientMessage }; foreach (var client in Clients) { if (client.Key != clientName) { SendMessage(client.Value, message); } } } SendMessage(IConnection connection, Message message) { var messageBytes = MessageConverter.ToBytes(message); connection.Send(new NetworkData { Buffer = messageBytes, Length = messageBytes.Length }); } }
3.HeliosChat.Client聊天服务的客户端