SuperSocket服务端与客户端搭建
本文记录使用SuperSocket搭建Socket服务端,然后搭建客户端与之通信
环境:.Net 4.5
一、先说服务端
创建一个控制台SuperSocketServer,创建会话类:MyServerSession
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class MyServerSession:AppSession<MyServerSession> { public override void Send( string message) { Console.WriteLine( "发送消息:" +message); base .Send(message); } protected override void OnSessionStarted() { Console.WriteLine( "Session已启动" ); base .OnSessionStarted(); } protected override void OnInit() { this .Charset = Encoding.GetEncoding( "gb2312" ); base .OnInit(); } protected override void HandleUnknownRequest(StringRequestInfo requestInfo) { Console.WriteLine( "未知请求" ); base .HandleUnknownRequest(requestInfo); } } |
分别表示4个状态和动作,一看就明白。
然后创建服务类:MyServer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class MyServer:AppServer<MyServerSession> { protected override bool Setup(IRootConfig rootConfig, IServerConfig config) { Console.WriteLine( "正在准备配置文件" ); return base .Setup(rootConfig, config); } protected override void OnStarted() { Console.WriteLine( "服务已启动" ); base .OnStarted(); } protected override void OnStopped() { Console.WriteLine( "服务已停止" ); base .OnStopped(); } protected override void OnNewSessionConnected(MyServerSession session) { Console.WriteLine( "新链接进入:" + session.LocalEndPoint.Address.ToString() + ":" + session.RemoteEndPoint.Port + "(" + session.SessionID + ")" + ",时间:" + DateTime.Now); base .OnNewSessionConnected(session); } protected override void OnSessionClosed(MyServerSession session, CloseReason reason) { Console.WriteLine( "链接关闭:" + session.LocalEndPoint.Address.ToString() + ":" + session.RemoteEndPoint.Port + "(" + session.SessionID + ")" + ",时间:" + DateTime.Now); base .OnSessionClosed(session, reason); } } |
表示服务器的4个状态,这些状态可以根据业务进行扩展
再创建命令类:ECHO执行客户端的命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | public class ECHO: CommandBase<MyServerSession, StringRequestInfo> { public override void ExecuteCommand(MyServerSession session, StringRequestInfo requestInfo) { if (requestInfo.Parameters.Length < 2) return ; string cmd = requestInfo.Parameters[0]; switch (cmd) { case "heart" : // heart 2 session.Send( "ok" ); break ; case "hello" : // hello 2 session.Send( "你说:" + requestInfo.Parameters[1]); break ; case "login" : // login 我 000 000 string userID = requestInfo.Parameters[1]; Console.WriteLine(userID + "登录成功" ); break ; case "sendto" : //sendto 我ID 他ID 内容 rev.Send(requestInfo.Parameters[3]); Console.WriteLine( string .Format( "{0}对{1}说:{2}" , requestInfo.Parameters[1],requestInfo.Parameters[2], requestInfo.Parameters[3])); break ; default : break ; } if (requestInfo.Parameters[0] == "all" ) { var sessions = session.AppServer.GetAllSessions(); foreach ( var item in sessions) { item.Send(requestInfo.Body); } } //根据参数个数或者其他条件判断,来进行一些自己的操作 //if (requestInfo.Parameters.Length == 2) //{ // Console.WriteLine("调用成功"); // session.Send(string.Format("{0}:{1},已经成功接收到你的请求\r\n", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port)); //} //else //{ // session.Send("参数不正确\r\n"); //} //session.Send(requestInfo.Body); } } |
这个类里面列举了执行动作判断,消息群发,一对一发,当然叶可以一对多
最后是启动服务main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | static void Main( string [] args) { IBootstrap bootstrap = BootstrapFactory.CreateBootstrap(); if (!bootstrap.Initialize()) { Console.WriteLine(DateTime.Now + ":Socket初始化失败\r\n" ); return ; } var result = bootstrap.Start(); foreach ( var server in bootstrap.AppServers) { if (server.State == ServerState.Running) { Console.WriteLine(DateTime.Now + ":serverName为:" + server.Name + "Socket运行中\r\n" ); Console.Read(); } else { Console.WriteLine(DateTime.Now + ":serverName为:" + server.Name + "Socket启动失败\r\n" ); } } } |
也是一看就能明白,还有配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <configuration> <configSections> <!--log 日志记录--> <section name= "log4net" type= "System.Configuration.IgnoreSectionHandler" /> <!--SocketEngine--> <section name= "superSocket" type= "SuperSocket.SocketEngine.Configuration.SocketServiceConfig, SuperSocket.SocketEngine" /> </configSections> <!--配置SocketServer路径--> <superSocket> <servers> <server name= "MySocket" textEncoding= "gb2312" serverType= "SuperSocketServer.MyServer, SuperSocketServer" ip= "Any" port= "2018" maxConnectionNumber= "100" > </server> </servers> </superSocket> <startup> <supportedRuntime version= "v4.0" sku= ".NETFramework,Version=v4.5" /> </startup> </configuration> |
全部的引用是这几个:
二、再说客户端
目前代码较为简单,实现了心跳与断线重连
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | class Program { private static AsyncTcpSession client; static System.Timers.Timer timer = null ; private int port = 2018; static void Main( string [] args) { new Program().Link(); string input = Console.ReadLine(); while (input != "exit" && ! string .IsNullOrEmpty(input)) { if (client != null && client.IsConnected) { var msg = System.Text.Encoding.Default.GetBytes( "echo hello " + input + "\r\n" ); client.Send(msg,0, msg.Length); input = Console.ReadLine(); } } } private void Link() { client = new AsyncTcpSession(); client.Connected += OnClientConnected; client.Error += OnClientError; client.Closed += OnClientClosed; // 收到服务器数据事件 client.DataReceived += client_DataReceived; //每10s发送一次心跳或尝试一次重连 timer = new System.Timers.Timer(10000); timer.Elapsed += new System.Timers.ElapsedEventHandler((s, x) => { //心跳包 if (client.IsConnected) { var heartMsg = System.Text.Encoding.Default.GetBytes( "echo heart 2\r\n" ); client.Send(heartMsg,0, heartMsg.Length); } //断线重连 else if (!client.IsConnected) { client.Connect( new IPEndPoint(IPAddress.Parse( "127.0.0.1" ), port)); } }); timer.Enabled = true ; timer.Start(); } private void OnClientConnected( object sender, EventArgs e) { Console.WriteLine( "已连接" + '\n' ); } private void OnClientClosed( object sender, EventArgs e) { Console.WriteLine( "已断开" + '\n' ); } private void OnClientError( object sender, ErrorEventArgs e) { Console.WriteLine($ "错误:{e.Exception.Message}" + '\n' ); } void client_DataReceived( object sender, DataEventArgs e) { string msg = Encoding.Default.GetString(e.Data); Console.WriteLine(msg.Trim( '\0' )); } } |
引用如下:
控制台版代码下载,压缩包里面带了tcptool可以不用客户端测试,记得每个命令完了要敲回车
Winform版代码下载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?