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 等等)都有相应的代码折叠展开功能,如下图所示,极大的方便了我们的编码工作.
随机推荐
- 如何配置CentOS 7网络
不久之前在配置CentOS 7网络,记录一下操作过程. CentOS 7,你可以按照以下步骤配置网络: 打开终端,输入命令查看本台服务器的IP信息. ip a 输入命令查看网关. ip r 输入命令查 ...
- 跨境 ERP 积加系统与金蝶云星空系统数据集成对接方案
方案简介 由于积加ERP 系统专注服务于亚马逊跨境电商是非常复杂和庞大的应用系统,具有非常丰富的业务流程.复杂的系统架构和服务接口.主要涉及系统解决店铺运营,店铺管理,供应链管理,协同智能补货.采用& ...
- SQLBI_精通DAX课程笔记_03_计算列
计算列是由DAX在表中生成的列,逐行计算并储存在模式之中. 以下链接是采悟老师关于度量值和计算列的区别的文章,可以同步查看. https://zhuanlan.zhihu.com/p/75462046 ...
- [ABC261A] Intersection
Problem Statement We have a number line. Takahashi painted some parts of this line, as follows: Firs ...
- SpringBoot整合Liquibase
1.是什么? Liquibase官网 Liquibase是一个开源的数据库管理工具,可以帮助开发人员管理和跟踪数据库变更.它可以与各种关系型数据库和NoSQL数据库一起使用,并提供多种数据库任务自动化 ...
- stackoverflow怎么解决
stackoverflow怎么解决 栈溢出的可能原因: 函数递归调用层次过深 ,每调用一次,函数的参数.局部变量等信息就压一次栈,并且没有及时出栈. 局部变量体积太大 分析:每一个 JVM 线程都拥有 ...
- 编写.NET的Dockerfile文件构建镜像
创建一个WebApi项目,并且创建一个Dockerfile空文件,添加以下代码,7.0代表的你项目使用的SDK的版本,构建的时候也需要选择好指定的镜像tag FROM mcr.microsoft.co ...
- MySQL部署后配置
授权root用户登录 #仅本地登录,修改密码用 alter user root@'localhost' identified with mysql_native_password by'******* ...
- EasyDO这么好用!别家的运维小哥都馋哭了
运维这份工作似乎总是被人误会- 修服务器的 接网线的 盯监控的 维护系统的 说啥的都有,平常人都不太知道运维是干啥的 跟小编来探一探云掣MSP服务线运维小哥的实际运维工作? 运维小哥一部分日常工作就是 ...
- 在linux系统上怎么获取命令的帮助信息及man文档划分
如何在linux系统上获取命令的帮助信息及man文档的章节划分 1.命令 -- help 2.man 命令 后者更加详细 首先帮助中尖括号<>和方括号[]以及省略号...的含义, 在方括号 ...