C# SuperSocket 手把手教你入门 傻瓜教程---1(服务器单向接收客户端发送数据)
C# SuperSocket 手把手教你入门 傻瓜教程---2(服务器和客户端双向通信)
C# SuperSocket 手把手教你入门 傻瓜教程---3(Telnet服务器和客户端请求处理)
C# SuperSocket 手把手教你入门 傻瓜教程---4(创建一个服务器和多客户端双向通信程序)
C# SuperSocket 手把手教你入门 傻瓜教程---5(探索自定义AppServer、AppSession,Conmmand,用配置文件App.comfig启动服务器)
C# SuperSocket 手把手教你入门 傻瓜教程---6(CommandLineProtocol---命令行协议)
C# SuperSocket 手把手教你入门 傻瓜教程---7(自定义CommandLineProtocol---命令行协议)
C# SuperSocket 手把手教你入门 傻瓜教程-8(TerminatorReceiveFilter - 结束符协议)
目录
一、新建一个SuperSocket服务器项目
二、安装SuperSocket和SuperSocket.Engine
三、编写程序代码
四、验证
SuperSocket是一个轻量级,跨平台而且可扩展的Net/Mono Socket服务器程序框架。你无须了解如何使用 Socket,如何维护Socket连接和Socket如何工作,但是你却可以使用SuperSocket很容易的开发出一款Socket服务器端软件,例如游戏服务器,GPS 服务器, 工业控制服务和数据采集服务器等等。
接下来开始我们的开发,首先我们需要安装SuperSocket相关程序包,我们新建一个项目开发SuperSocket服务器,然后打开NuGet程序包管理器,搜索SuperSocket ,下载安装SuperSocket和SuperSocket.Engine。
新建一个SuperSocket服务器项目(WINDOWS窗体应用),参见下图。
安装SuperSocket和SuperSocket.Engine之前,引用中的组件参见下图。
1、进入【管理NuGet程序包】
鼠标右键单击【引用】,弹出下拉菜单,在下拉菜单中选中【管理NuGet程序包(N)】
2、安装SuperSocket
(1)、【浏览】选项卡下面的输入框中输入SuperSocket
(2)、过一会下面会出现"SuperSocket 由Kerry Jiang,285K个下载 v1.6.6.1"
(3)、鼠标点击"SuperSocket 由Kerry Jiang,285K个下载 v1.6.6.1",右边会出现"版本:最新稳定版1.6.6.1"
(4)、点击"版本:最新稳定版1.6.6.1"右边的【安装】按钮
弹出“预览更改”窗口,点击【确定】按钮
弹出“接受许可”窗口,点击【我接受】按钮
然后开始安装 SuperSocket,安装完毕,参见右边引用中的组件如下图所示,可以观察到增加了4个组件:
log4net、SuperSocket.Common,SuperSocket.Facility,SuperSocket.SocketBase
3、安装SuperSocket.Engine
(1)、鼠标点击"SuperSocket.Engine 由Kerry Jiang,165K个下载 v1.6.6.1",右边会出现"版本:1.6.6.1"
(2)、点击"版本:1.6.6.1"右边的【安装】按钮
弹出“预览更改”窗口,点击【确定】按钮
弹出“接受许可”窗口,点击【我接受】按钮
然后开始安装 SuperSocket.Engine,安装完毕,参见右边引用中的组件如下图所示,可以观察到增加了2个组件:
SuperSocket.SocketEngine,SuperSocket.SocketService。
1、Form1窗体增加3个label,Name依次命名为label1,label2,label3,标签内容依次为:IP地址,端口、客户端列表。
2、Form1窗体增加3个TextBox,Name依次为textBox_ip,textBox_port,textBox_send,TEXT内容依次为:127.0.0.1,5000、空。
3、Form1窗体增加2个Button,Name依次为btn_Listen,btn_send,TEXT内容依次为:开启监听,发送数据。
4、Form1窗体的【客户端列表】右边增加1个ComboBox,Name为comboBox_SocketList。
4、Form1窗体增加1个RichTextBox,Name为richTextBox1。
5、Form1.cs中编写如下代码
完整的源程序如下:
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 SuperSocket;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
namespace SuperSocket
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox_ip.Text = "127.0.0.1";
textBox_port.Text = "5000";
}
//----------------------------------------------------------------------
//AppServer 代表了监听客户端连接,承载TCP连接的服务器实例。
//理想情况下,我们可以通过AppServer实例获取任何你想要的客户端连接,
//服务器级别的操作和逻辑应该定义在此类之中。
//----------------------------------------------------------------------
AppServer appServer;
string ipAddress_Connect;
string ipAddress_Close;
string ipAddress_Receive;
//存储session和对应ip端口号的泛型集合
Dictionary sessionList = new Dictionary();
enum OperateType
{
Add = 1, //添加
Remove = 2 //移除
}
private void btn_Listen_Click(object sender, EventArgs e)
{
appServer = new AppServer();
if (!appServer.Setup(int.Parse(textBox_port.Text)))
{
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText("Failed to Setup" + "\r\n"); }));
return;
}
if (!appServer.Start())
{
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText("Failed to Start" + "\r\n"); }));
return;
}
else
{
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText("开启监听" + "\r\n"); }));
}
//SuperSocket自定义了三个事件 ,连接事件,接收事件,关闭事件
appServer.NewSessionConnected += appServer_NewSessionConnected; //连接事件
appServer.NewRequestReceived += appServer_NewRequestReceived; //接收事件
appServer.SessionClosed += appServer_SessionClosed; //关闭事件
}
private void btn_send_Click(object sender, EventArgs e)
{
//从客户端列获取想要发送数据的客户端的ip和端口号,然后从sessionList中获取对应session然后调用send()发送数据
if (comboBox_SocketList.Items.Count != 0)
{
if (comboBox_SocketList.SelectedItem == null)
{
MessageBox.Show("请选择一个客户端发送数据!");
return;
}
else
{
sessionList[comboBox_SocketList.SelectedItem.ToString()].Send(textBox_send.Text);
}
}
else
{
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText("当前没有正在连接的客户端!" + "\r\n"); }));
}
}
///
/// 接收连接
///
///
void appServer_NewSessionConnected(AppSession session)
{
//有新连接的时候,添加记录 session.LocalEndPoint属性获取当前session的ip和端口号
//AppSession 代表一个和客户端的逻辑连接,基于连接的操作应该定于在该类之中。你可以用该类的实例发送数据到客户端,接收客户端发送的数据或者关闭连接。
//获取远程客户端的ip端口号
ipAddress_Connect = session.RemoteEndPoint.ToString();
Combobox_Handle_ipAddress(ipAddress_Connect, OperateType.Add);
sessionList.Add(ipAddress_Connect, session);
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(ipAddress_Connect + "已连接!" + "\r\n"); }));
}
///
/// 接收数据
///
///
///
void appServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo)
{
//requestInfo.Key 是请求的命令行用空格分隔开的第一部分
//requestInfo.Parameters 是用空格分隔开的其余部分
//requestInfo.Body 是出了请求头之外的所有内容
ipAddress_Receive = session.RemoteEndPoint.ToString();
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText("收到" + ipAddress_Receive + "数据: " + requestInfo.Key + " " + requestInfo.Body + "\r\n"); }));
}
///
/// 关闭连接
///
///
///
///
//static void appServer_SessionClosed(AppSession session, CloseReason value)
void appServer_SessionClosed(AppSession session, SocketBase.CloseReason value)
{
ipAddress_Close = session.RemoteEndPoint.ToString();
Combobox_Handle_ipAddress(ipAddress_Close, OperateType.Remove);
sessionList.Remove(ipAddress_Close);
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(ipAddress_Close + "已关闭连接!" + "\r\n"); }));
}
///
/// combobox操作
///
///
/// add 添加项/remove 移除项
private void Combobox_Handle_ipAddress(string ipAddress, OperateType operateType)
{
if (operateType == OperateType.Add)
{
comboBox_SocketList.Invoke(new Action(() => { comboBox_SocketList.Items.Add(ipAddress); }));
}
if (operateType == OperateType.Remove)
{
comboBox_SocketList.Invoke(new Action(() => { comboBox_SocketList.Items.Remove(ipAddress); }));
}
}
}
}
这里说明几点:
(1)、appServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo)
方法中的StringRequestInfo是包含请求信息的,
requestInfo.Key 是请求的命令行用空格分隔开的第一部分
requestInfo.Parameters 是用空格分隔开的其余部分,用空格分割开的字符串数组
requestInfo.Body 是出了请求头之外的所有内容,是一个字符串
(2)、这里requestInfo是客户端发送过来严格按照:请求头 请求参数 请求参数 请求参数 \r\n 的格式发送,空格隔开的第一部分是请求头,后边用空格分割后组成的数据就是请求参数,而且必须是以回车换行结尾 SuperSocket才能正确接收。
(3)、这里请求头和请求参数用什么分割是可以自定义,我们可以自定义AppServer类,继承APPServer类,然后使用下面的代码扩展命令行协议
比如用":"分割请求头和请求参数,用","分隔请求参数。
public class YourServer : AppServer
{
public YourServer()
: base(new CommandLineReceiveFilterFactory(Encoding.Default, new BasicRequestInfoParser(":", ",")))
{
}
}
接下来我们开始测试,默认使用5000端口,开启监听,我们使用SocketTool工具创建二个客户端,一起访问服务器。
1、SocketTool工具
2、运行服务器程序
运行服务器程序,然后点击【开启监听】按钮。
3、运行第一个客户端程序
鼠标先点击TCP_Client,然后点击【创建】按钮,弹出【创建Socket】对话框,在【创建Socket】对话框的【对方IP】输入127.0.0.1,在【对方端口】输入5000,然后点击【确定】按钮。
鼠标在客户端软件(TCP/UDP Socket调试工具V2.2)上点击【连接】按钮,参见下图,服务器监听到客户端,同时服务器和客户端连接成功。
首先在客户端列表中找到刚刚连接成功的客户端连接,然后服务器给客户端发送字符串"I AM SERVER!"
可以观察到客户端收到服务器发送的字符串"I AM SERVER!"
客户端给服务器发送字符串"I am Client1"
警告:客户端发送数据一定以回车换行符作为结尾,这是SuperSocket的强制要求。因此客户端输入完字符串"I am Client1"之后,必须再敲回车换行符。
4、运行第二个客户端程序
鼠标先点击TCP_Client,然后点击【创建】按钮,弹出【创建Socket】对话框,在【创建Socket】对话框的【对方IP】输入127.0.0.1,在【对方端口】输入5000,然后点击【确定】按钮。
鼠标点击【连接】按钮,可以在服务器观察到连接成功。服务器的客户端列表上出现了客户的连接。
首先在客户端列表中找到刚刚连接成功的客户端连接,然后服务器给客户端发送字符串“Hello Client2!!!”
可以观察到客户端收到服务器发送的字符串“Hello Client2!!!”
客户端2给服务器发送字符串“Hello sever I am Client2!!!”
警告:客户端发送数据一定以回车换行符作为结尾,这是SuperSocket的强制要求。因此客户端输入完字符串“Hello sever I am Client2!!!”之后,必须再敲回车换行符。
可以观察到服务器收到了客户端2发送的字符串。
源程序参见如下链接:
SuperSocket(最简单的服务器和多客户端双向通信程序).zip_supersocket长连接-其它文档类资源-CSDN下载
源程序中包含SocketTool.exe TCP&UPD测试工具
致谢:
黄昏前黎明后