最近在csdn上参考多位大神的SuperSocket.ClientEngine的示例,发现无法触发接收事件。经本人仔细查看SuperSocket.ClientEngine的源代码【可通过nuget下载源代码】,可以通过使用EasyClient<StringPackageInfo>这个泛型类的NewPackageReceived事件进行过滤接收操作。下面的示例演示开始和结束标记过滤的演示程序。
一、在VS2017中新建Windows窗体应用程序,命名为SuperSocketClientDemo,选择.net framework 4.5,在默认的Winform窗体上增加如下控件:如下图
在项目中添加SuperSocket.ClientEngine.dll和SuperSocket.ProtoBase.dll的引用。
二、新建继承于开始与结束标记的实体类ReceiveFilter,该类源代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SuperSocket.ProtoBase;
namespace SuperSocketClientDemo
{
public class ReceiveFilter : BeginEndMarkReceiveFilter<StringPackageInfo>
{
byte[] BeginMark;
byte[] EndMark;
/// <summary>
/// 过滤器
/// </summary>
/// <param name="beginMark">开始字符串 或 开始字节数组</param>
/// <param name="endMark">结束字符串 或 结束字节数组</param>
public ReceiveFilter(byte[] beginMark, byte[] endMark) : base(beginMark, endMark)
{
this.BeginMark = beginMark;
this.EndMark = endMark;
}
/// <summary>
/// 经过过滤器,收到的字符串会到这个函数
/// </summary>
/// <param name="bufferStream"></param>
/// <returns></returns>
public override StringPackageInfo ResolvePackage(IBufferStream bufferStream)
{
获取接收到的完整数据,包括头和尾
//string body = bufferStream.ReadString((int)bufferStream.Length, Encoding.Default);
掐头去尾,只返回中间的数据
//body = body.Substring(BeginMark.Length, body.Length - EndMark.Length - BeginMark.Length);
//Skip(int count):从数据源跳过指定的字节个数。直接获取过滤后的数据
string body = bufferStream.Skip(BeginMark.Length).ReadString((int)bufferStream.Length - BeginMark.Length - EndMark.Length, Encoding.Default);
return new StringPackageInfo("", body, new string[] { });
}
}
}
三、Form1.cs的相关程序源代码如下(忽略设计器自动生成的代码):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SuperSocket.ClientEngine;
using SuperSocket.ProtoBase;
namespace SuperSocketClientDemo
{
public partial class Form1 : Form
{
/// <summary>
/// socket客户端对象
/// </summary>
EasyClient<StringPackageInfo> mClient = null;
public Form1()
{
InitializeComponent();
mClient = new EasyClient<StringPackageInfo>();
// 连接断开事件
mClient.Closed += ClientClosed;
// 收到服务器数据事件
mClient.NewPackageReceived += MClient_NewPackageReceived; ;
// 连接到服务器事件
mClient.Connected += ClientConnected;
// 发生错误的处理
mClient.Error += ClientError;
}
void ClientClosed(object sender, EventArgs e)
{
DisplayInfo("客户端连接已断开");
}
private void MClient_NewPackageReceived(object sender, PackageEventArgs<StringPackageInfo> e)
{
EasyClient<StringPackageInfo> tempClient = sender as EasyClient<StringPackageInfo>;
IPEndPoint endPoint = tempClient.LocalEndPoint as IPEndPoint;
DisplayInfo($"客户端【{endPoint.Address}:{endPoint.Port}】接收到服务端过滤后的数据:{e.Package.Body}");
}
void ClientConnected(object sender, EventArgs e)
{
DisplayInfo("客户端已连接成功");
}
void ClientError(object sender, ErrorEventArgs e)
{
DisplayInfo("出现错误:"+ e.Exception.Message);
}
private void btnConnect_Click(object sender, EventArgs e)
{
if (txtBeginMark.Text.Trim().Length == 0 || txtEndMark.Text.Trim().Length == 0)
{
DisplayInfo("开始标记、结束标记都不能为空");
return;
}
byte[] beginMark = Encoding.Default.GetBytes(txtBeginMark.Text.Trim());
byte[] endMark = Encoding.Default.GetBytes(txtEndMark.Text.Trim());
// Initialize the client with the receive filter and request handler
mClient.Initialize(new ReceiveFilter(beginMark, endMark));
//连接服务端
string strIP = txtIP.Text;
int iPort = int.Parse(txtPort.Text);
Task<bool> rst = mClient.ConnectAsync(new IPEndPoint(IPAddress.Parse(strIP), iPort));
bool connectResult = rst.Result;
DisplayInfo($"连接到【{strIP}:{iPort}】{(connectResult ? "成功":"失败")}.");
if (connectResult)
{
SendCommand("Hello Server!");
}
}
/// <summary>
/// 显示富文本框的消息
/// </summary>
/// <param name="message"></param>
private void DisplayInfo(string message)
{
this.BeginInvoke(new Action(() =>
{
if (richTextBox1.TextLength >= 10240)
{
richTextBox1.Clear();
}
richTextBox1.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} --> {message}\n");
}));
}
/// <summary>
/// 发送命令消息
/// </summary>
/// <param name="message"></param>
public void SendCommand(string message)
{
if (mClient.IsConnected)
{
byte[] arrBytes = Encoding.Default.GetBytes(message);
// Send data to the server
mClient.Send(arrBytes);
}
else
{
throw new InvalidOperationException("已断开连接,无法发送数据");
}
}
}
}
四、程序运行,先开一个Socket助手作为服务端。然后运行窗体程序。
如果服务端发送:#你好$#AAA$#222$ ,则将会触发接收事件多次
发送不是#开头的数据,非法操作则导致连接中断
如图: