SuperSocket 简单示例
这是一个SuperSocket 简单示例,包括服务端和客户端。
一、首先使用NuGet安装SuperSocket和SuperSocket.Engine

二、实现IRequestInfo(数据包):
数据包格式:
包头4个字节,前2个字节是请求命令,后2个字节是正文长度

using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace SuperSocketServer
{
public class MyRequestInfo : IRequestInfo
{
public MyRequestInfo(byte[] header, byte[] bodyBuffer)
{
Key = ASCIIEncoding.ASCII.GetString(new byte[] { header[0], header[1] });
Data = bodyBuffer;
} public string Key { get; set; } public byte[] Data { get; set; } public string Body
{
get
{
return Encoding.UTF8.GetString(Data);
}
}
}
}
三、实现FixedHeaderReceiveFilter(数据包解析):

using SuperSocket.Facility.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace SuperSocketServer
{
public class MyReceiveFilter : FixedHeaderReceiveFilter<MyRequestInfo>
{
public MyReceiveFilter() : base(4)
{ } protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
{
return BitConverter.ToInt16(new byte[] { header[offset + 2], header[offset + 3] }, 0);
} protected override MyRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
{
byte[] body = bodyBuffer.Skip(offset).Take(length).ToArray();
return new MyRequestInfo(header.Array, body);
}
}
}
四、实现AppSession:

using SuperSocket.SocketBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace SuperSocketServer
{
public class MySession : AppSession<MySession, MyRequestInfo>
{
public MySession()
{ } protected override void OnSessionStarted()
{ } protected override void OnInit()
{
base.OnInit();
} protected override void HandleUnknownRequest(MyRequestInfo requestInfo)
{ } protected override void HandleException(Exception e)
{ } protected override void OnSessionClosed(CloseReason reason)
{
base.OnSessionClosed(reason);
}
}
}
五、实现AppServer:

using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils; namespace SuperSocketServer
{
public class MyServer : AppServer<MySession, MyRequestInfo>
{
public MyServer() : base(new DefaultReceiveFilterFactory<MyReceiveFilter, MyRequestInfo>())
{
this.NewSessionConnected += MyServer_NewSessionConnected;
this.SessionClosed += MyServer_SessionClosed;
} protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
{
return base.Setup(rootConfig, config);
} protected override void OnStarted()
{
base.OnStarted();
} protected override void OnStopped()
{
base.OnStopped();
} void MyServer_NewSessionConnected(MySession session)
{
LogHelper.Log("新客户端连接,SessionID=" + session.SessionID.Substring(session.SessionID.Length - 6).ToUpper());
} void MyServer_SessionClosed(MySession session, CloseReason value)
{
LogHelper.Log("客户端失去连接,SessionID=" + session.SessionID.Substring(session.SessionID.Length - 6).ToUpper() + ",原因:" + value);
}
}
}
六、实现CommandBase<MySession, MyRequestInfo>:

using SuperSocket.SocketBase.Command;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils; namespace SuperSocketServer
{
public class EC : CommandBase<MySession, MyRequestInfo>
{
public override void ExecuteCommand(MySession session, MyRequestInfo requestInfo)
{
LogHelper.Log("客户端 " + session.SessionID.Substring(session.SessionID.Length - 6).ToUpper() + " 发来消息:" + requestInfo.Body);
byte[] bytes = ASCIIEncoding.UTF8.GetBytes("消息收到");
session.Send(bytes, 0, bytes.Length);
}
}
}
七、服务端Form1.cs代码:

using SuperSocket.SocketBase.Config;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils; namespace SuperSocketServer
{
public partial class Form1 : Form
{
private MyServer _myServer; public Form1()
{
InitializeComponent();
LogHelper.Init(this, txtLog);
} private void Form1_Load(object sender, EventArgs e)
{
_myServer = new MyServer();
ServerConfig serverConfig = new ServerConfig()
{
Port = 2021
};
_myServer.Setup(serverConfig);
_myServer.Start();
} private void button1_Click(object sender, EventArgs e)
{
foreach (MySession session in _myServer.GetAllSessions())
{
byte[] bytes = ASCIIEncoding.UTF8.GetBytes("服务端广播消息");
session.Send(bytes, 0, bytes.Length);
}
}
}
}
八、客户端Form1.cs代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace SuperSocketClient
{
public partial class Form1 : Form
{
private Socket _socket; private NetworkStream _socketStream; public Form1()
{
InitializeComponent();
} private void Form1_Load(object sender, EventArgs e)
{
EndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2021);
_socket = new Socket(serverAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_socket.Connect(serverAddress);
_socketStream = new NetworkStream(_socket); //SocketAsyncEventArgs socketAsyncArgs = new SocketAsyncEventArgs();
//byte[] buffer = new byte[10240];
//socketAsyncArgs.SetBuffer(buffer, 0, buffer.Length);
//socketAsyncArgs.Completed += ReciveAsync;
//_socket.ReceiveAsync(socketAsyncArgs); Receive(_socket); } private void button1_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
Random rnd = new Random();
string cmd = "EC";
string msg = "测试消息00" + rnd.Next(0, 100).ToString("00");
Send(cmd, msg);
});
} public void Send(string cmd, string msg)
{
byte[] cmdBytes = Encoding.ASCII.GetBytes(cmd);
byte[] msgBytes = Encoding.UTF8.GetBytes(msg);
byte[] lengthBytes = BitConverter.GetBytes((short)msgBytes.Length); _socketStream.Write(cmdBytes, 0, cmdBytes.Length);
_socketStream.Write(lengthBytes, 0, lengthBytes.Length);
_socketStream.Write(msgBytes, 0, msgBytes.Length);
_socketStream.Flush();
Log("发送:" + msg);
} private void ReciveAsync(object obj, SocketAsyncEventArgs e)
{
if (e.BytesTransferred > 0)
{
string data = ASCIIEncoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred);
Log("接收:" + data);
}
} private void Receive(Socket socket)
{
Task.Factory.StartNew(() =>
{
try
{
while (true)
{
byte[] buffer = new byte[10240];
int receiveCount = _socket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
if (receiveCount > 0)
{
string data = ASCIIEncoding.UTF8.GetString(buffer, 0, receiveCount);
Log("接收:" + data);
}
}
}
catch (Exception ex)
{
Log("Receive出错:" + ex.Message + "\r\n" + ex.StackTrace);
}
}, TaskCreationOptions.LongRunning);
} #region Log
/// <summary>
/// 输出日志
/// </summary>
private void Log(string log)
{
if (!this.IsDisposed)
{
this.BeginInvoke(new Action(() =>
{
txtLog.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + " " + log + "\r\n\r\n");
}));
}
}
#endregion }
}
辅助工具类LogHelper:

using SuperSocketServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace Utils
{
public class LogHelper
{
private static Form1 _frm; private static TextBox _txtLog; public static void Init(Form1 frm, TextBox txt)
{
_frm = frm;
_txtLog = txt;
} /// <summary>
/// 输出日志
/// </summary>
public static void Log(string log)
{
if (!_frm.IsDisposed)
{
_frm.BeginInvoke(new Action(() =>
{
_txtLog.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + " " + log + "\r\n\r\n");
}));
}
} }
}
测试截图:

问题:
1、客户端使用SocketAsyncEventArgs异步接收数据,第一次能收到数据,后面就收不到了,不知道什么原因,同步接收数据没问题
2、SuperSocket源码中的示例和网上相关的博客,客户端要么是原生Socket实现,要么是Socket调试工具,客户端不需要复杂一点的功能或数据结构吗?客户端不需要解包吗?SuperSocket不能用来写客户端吗?
SuperSocket 简单示例的更多相关文章
- Linux下的C Socket编程 -- server端的简单示例
Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...
- C# 构建XML(简单示例)
C# 构建XML的简单示例: var pars = new Dictionary<string, string> { {"url","https://www. ...
- 根据juery CSS点击一个标签弹出一个遮罩层的简单示例
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- ACEXML解析XML文件——简单示例程序
掌握了ACMXML库解析XML文件的方法后,下面来实现一个比较完整的程序. 定义基本结构 xml文件格式如下 <?xml version="1.0"?> <roo ...
- demo工程的清单文件及activity中api代码简单示例
第一步注册一个账户,并创建一个应用.获取app ID与 app Key. 第二步下载sdk 第三步新建工程,修改清单文件,导入相关的sdk文件及调用相应的api搞定. 3.1 修改清单文件,主要是加入 ...
- spring-servlet.xml简单示例
spring-servlet.xml简单示例 某个项目中的spring-servlet.xml 记下来以后研究用 <!-- springMVC简单配置 --> <?xml versi ...
- SignalR 简单示例
一.什么是 SignalR ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of add ...
- Web API 简单示例
一.RESTful和Web API Representational State Transfer (REST) is a software architecture style consisting ...
- XML引入多scheme文件约束简单示例
XML引入多scheme文件约束简单示例,用company.xsd和department.xsd来约束company.xml: company.xsd <?xml version="1 ...
- HTML-003-模拟IDE代码展开收起功能简单示例
当先我们在日常的编程开发工作中使用编程工具(例如 Eclipse.Sublime 等等)都有相应的代码折叠展开功能,如下图所示,极大的方便了我们的编码工作.
随机推荐
- 后台获取的map集合封装json
let list = [] let arr = {'a':'1','b':'2','c':'3','d':'4'} for(var key in arr){ console.log("key ...
- 🔥🔥Java开发者的Python快速进修指南:实战之跳表pro版本
之前我们讲解了简易版的跳表,我希望你能亲自动手实现一个更完善的跳表,同时也可以尝试实现其他数据结构,例如动态数组或哈希表等.通过实践,我们能够发现自己在哪些方面还有所欠缺.这些方法只有在熟练掌握之后才 ...
- vue禁止浏览器F5进行刷新和监听浏览器刷新事件
项目中有个这样的需求: 进入视频播放页后,添加一个标识,为了防止用户一次播放多个视频,当离开该页面后,如果是从当前正在播放的视频页面离开的,则离开播放页时清除标识,如果是不是则不清除,并且禁止用户按F ...
- 探索 Web API:SpeechSynthesis 与文本语言转换技术
一.引言 随着科技的不断发展,人机交互的方式也在不断演变.语音识别和合成技术在人工智能领域中具有重要地位,它们为残障人士和日常生活中的各种场景提供了便利.Web API 是 Web 应用程序接口的一种 ...
- 手把手教你搭建 Ceph+JuiceFS
Ceph 提供了对象存储,可作为存储引擎在 JuiceFS 中使用.这一组合非常适合云计算.大数据分析和机器学习等数据密集型应用场景. 在日常部署中可直接通过 Ceph RADOS 配合 JuiceF ...
- vue3+ts打开echarts的正确方式
实例项目使用 vite5 + vue3 + ts,项目地址 vite-vue3-charts,预览地址 https://weizwz.com/vite-vue3-charts 准备工作 1. 注册为百 ...
- ElasticSearch之Get index settings API
获取指定索引的参数的值. 获取指定索引的全部参数,命令样例如下: curl -X GET "https://localhost:9200/testindex_002/_settings?pr ...
- Python——第五章:time模块、datetime模块
time模块 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime,calendar(很少用,不讲),下面分别来介绍. 我们写程序时对时间 ...
- zabbix常用监控项
https://blog.csdn.net/xkjcf/article/details/78559273?locationNum=10&fps=1 agent.ping #agent是否在线 ...
- 春眠不觉晓,Java数据类型知多少?基础牢不牢看完本文就有数了
文编|JavaBuild 哈喽,大家好呀!我是JavaBuild,以后可以喊我鸟哥!俺滴座右铭是不在沉默中爆发,就在沉默中灭亡,一起加油学习,珍惜现在来之不易的学习时光吧,等工作之后,你就会发现,想学 ...