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 等等)都有相应的代码折叠展开功能,如下图所示,极大的方便了我们的编码工作.
随机推荐
- logstash 配置文件语法介绍
大家好,我是蓝胖子,之前在构建服务监控实践那个系列里,有提到用logstash来做日志的收集,但是对于logstash的配置文件语法没有做很详细的介绍,今天就来详细聊聊logstash配置文件的语法. ...
- 时间复杂度为 O(nlogn) 的排序算法
归并排序 归并排序遵循分治的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后合并这些子问题的解来建立原问题的解,归并排序的步骤如下: 划分:分解待排序的 n 个元素的 ...
- 解决IDEA加载maven工程缓慢
如图,哪里没有加哪里 -DarchetypeCatalog=internal
- C++ Qt开发:ProgressBar进度条组件
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍Progres ...
- Python 潮流周刊第 32 期(摘要)
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...
- ElasticSearch之Clear cache API
本方法用于清理缓存. 命令样例如下: curl -X POST "https://localhost:9200/testindex_001/_cache/clear?pretty" ...
- k8s 标签-2
目录 标签-2 node的角色 修改node节点的角色,将他的角色修改成他的主机名 标签的作用 Cordon,Drain以及污点 Cordon--告警警戒 Drain 驱逐演示 污点 污点的Cordo ...
- HDU 2709 Sumset DP 二进制
原题链接 题意 给我们一个整数k,要求我们将k分成若干个二的整数幂(1, 2, 4, 8...)的加和形式,问我们所有的分法中,本质不同(即某个2的幂的数量不同)的形式有多少种,k最多为1000000 ...
- spring-mvc 系列:获取请求参数(ServletAPI、形参、RequestParam、RequestHeader、CookieValue、POJO等方式)
目录 一.通过 ServletAPI 获取 二.通过控制器方法的形参获取请求参数 三.@RequestParam 四.@RequestHeader 五.@CookieValue 六.通过 POJO 获 ...
- GDAL创建JPG或PNG格式图像
目录 1. 概述 2. 实现 1. 概述 根据GDAL文档,JPG/PNG格式支持读取和批量写入,但不支持实时更新.也就是不支持Create()方法,但是支持CreateCopy()方法.也可能是由于 ...