新建项目步骤
- 在vs中创建一个空白解决方案,选择好路径。
- 在解决方案下创建项目。VisualC# → Windows → 控制台应用程序.
- 右键项目 → 属性 → 应用程序 → 目标框架 → .NET Framework 4.
- 右键引用→浏览添加supersocket需要的.dll文件。
- 右键项目新建文件夹Config,添加现有文件log4net.config和log4net.unix.config。这两个文件的属性按照要求进行设置即可。
- 调试运行出现错误。
右键引用 → .NET 添加错误提示中需要的.dll文件。
测试指令
Telnet测试指令
当一个类显示没有被包含进来的时候,需要根据API手册,找到相应的类。
当在使用Command时,调用自己写的APPSession和APPServer的时候出现了访问类型不一致的问题。原因是:自定义的AppSession的类的访问权限应该使用public进行限制。
经验
在AppServer中OnStartup方法已经过时了(obsolete),替代的方法是OnStarted方法。
- 在相对位置不同的类中引用其它路径下的类的时候,需要首先需要使用这个类的命名空间。
一个配置文件实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<configuration>
<configSections>
<section name="superSocket"
type="SuperSocket.SocketEngine.Configuration.SocketServiceConfig, SuperSocket.SocketEngine" />
</configSections>
<appSettings>
<add key="ServiceName" value="SupperSocketService" />
</appSettings>
<!--开启匹配功能-->
<superSocket xmlns="http://schema.supersocket.net/supersocket"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schema.supersocket.net/supersocket http://schema.supersocket.net/v1-6/supersocket.xsd">
<servers>
<server name="GameServer"
logFactory="ConsoleLogFactory"
serverTypeName="GameServer"
ip="Any"
port="2017"
>
</server>
</servers>
<!--type的第一个参数是服务器类的具体路径,第二个参数是项目名(是程序集名,而不是类的命名空间)-->
<serverTypes>
<add name="GameServer"
type="SuperSocketServer.Server1.GameServer, SuperSocketServer"/>
</serverTypes>
<!--为该服务器添加日志,生成的日志文件在bin/Debug/logs中进行查看;同时由于开启了日志功能,控制台也会打印相关的信息-->
<logFactories>
<add name="ConsoleLogFactory"
type="SuperSocket.SocketBase.Logging.ConsoleLogFactory, SuperSocket.SocketBase" />
</logFactories>
</superSocket>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
</configuration>Command运行不稳定啊啊啊
使用自定义RequestInfo,AppSession的固定数量分隔符协议
1
2
3
4
5
6
7
8
9public CounterReceiveFilter() : base((byte)'#', 11)
{
}
public MyAppServer()
: base(new DefaultReceiveFilterFactory< CounterReceiveFilter, RequestInfo>())
{
}使用自定义RequestInfo,AppSession的结束符协议协议
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34class TerReceiveFilter : TerminatorReceiveFilter<RequestInfoFirst>
{
public TerReceiveFilter()
: base(Encoding.Default.GetBytes("##")) //传入固定的请求大小
{
}
protected override RequestInfoFirst ProcessMatchedRequest(byte[] data, int offset, int length)
{
///使用一个变量之前必须给它分配相应的内存空间
RequestInfoFirst info=new RequestInfoFirst();
info.totalCmd_App = "Hello World";
return info;
}
}
class GameServer:AppServer<GameSession,RequestInfoFirst>
{
string TAG = "GameServer:";
/// <summary>
/// AppServer only has two constructors
/// </summary>
public GameServer()
: base(new DefaultReceiveFilterFactory<TerReceiveFilter, RequestInfoFirst>())
{
NewSessionConnected += GameServer_NewSessionConnected;
NewRequestReceived += GameServer_NewRequestReceived;
}
private void GameServer_NewRequestReceived(GameSession session, RequestInfoFirst requestInfo)
{
Console.WriteLine(requestInfo.totalCmd_App);
}
private void GameServer_NewSessionConnected(GameSession session)
{
Console.WriteLine(TAG + "GameServer_NewSessionConnected");
}当错误提示为“是否缺少using指令或程序集引用”时,可以采取以下办法:
- 去API中找相应出错方法的命名空间。
- 在IDE中找到出错方法的定义处,寻找相应的命名空间。
- 百度寻找相应方法的命名空间。
使用自定义RequestInfo,AppSession的头部格式固定且包含内容长度的协议
1 | class FixedReceiveFilter: FixedHeaderReceiveFilter<BinaryRequestInfo> |
特别注意
- session、server、command的定义方法:
1
2
3
4
5public class GameSession : AppSession<GameSession, BinaryRequestInfo>{}
public class GameServer : AppServer<GameSession, BinaryRequestInfo>{}
public class RESTART : CommandBase<GameSession, BinaryRequestInfo>{}从上面不难看出只要是使用的session的地方不论是server还是command,他们的另外一个RequestInfo参数必须是和Session中的RequestInfo的参数是一样的,否则会出现参数类型不匹配的错误。
C#中实现接口
https://www.cnblogs.com/ben-zhang/archive/2012/12/18/2823455.htmlSuperSocket实现接口举例
接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44// 摘要:
// Receive filter interface
//
// 类型参数:
// TRequestInfo:
// The type of the request info.
public interface IReceiveFilter<TRequestInfo> where TRequestInfo : global::SuperSocket.SocketBase.Protocol.IRequestInfo
{
// 摘要:
// Gets the size of the rest buffer.
int LeftBufferSize { get; }
//
// 摘要:
// Gets the next Receive filter.
IReceiveFilter<TRequestInfo> NextReceiveFilter { get; }
//
// 摘要:
// Gets the filter state.
FilterState State { get; }
// 摘要:
// Filters received data of the specific session into request info.
//
// 参数:
// readBuffer:
// The read buffer.
//
// offset:
// The offset of the current received data in this read buffer.
//
// length:
// The length of the current received data.
//
// toBeCopied:
// if set to true [to be copied].
//
// rest:
// The rest, the length of the data which hasn't been parsed.
TRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest);
//
// 摘要:
// Resets this instance to initial state.
void Reset();
}实现接口的类
1 | class XieReceiveFilter:IReceiveFilter<GameRequestInfo> |
RequestInfo
1
2
3
4public class GameRequestInfo:IRequestInfo
{
public string Key { get;set;}
}Session
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class GameSession : AppSession<GameSession, GameRequestInfo>
{
protected override void OnSessionStarted()
{
this.Send("Welcome to SuperSocket Telnet Server");
}
protected override void HandleUnknownRequest(GameRequestInfo requestInfo)
{
this.Send("Unknow request");
}
protected override void HandleException(Exception e)
{
this.Send("Application error: {0}", e.Message);
}
protected override void OnSessionClosed(CloseReason reason)
{
//add you logics which will be executed after the session is closed
base.OnSessionClosed(reason);
}
}Filter
1 | class XieReceiveFilter:IReceiveFilter<GameRequestInfo> |
FilterFactory
-
1
2
3
4
5
6
7class XieReceiveFilterFactory : IReceiveFilterFactory<GameRequestInfo>
{
public IReceiveFilter<GameRequestInfo> CreateFilter(IAppServer appServer, IAppSession appSession, IPEndPoint remoteEndPoint)
{
throw new NotImplementedException();
}
} Server
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class GameServer : AppServer<GameSession, GameRequestInfo>
{
string TAG = "GameServer:";
public GameServer()
: base(new XieReceiveFilterFactory())
{
NewSessionConnected += GameServer_NewSessionConnected;
NewRequestReceived += GameServer_NewRequestReceived;
}
private void GameServer_NewRequestReceived(GameSession session, GameRequestInfo requestInfo)
{
Console.WriteLine(requestInfo.ToString());
}
private void GameServer_NewSessionConnected(GameSession session)
{
Console.WriteLine(TAG + "GameServer_NewSessionConnected");
}
}