什么是模块化网络服务应用程序?
模块化网络服务应用程序 是通过 SOCKET 应用程序 提供框架 ,然后 通过一些方法 把你 编译的类(当然这些类必须实现一定的规则)添加到框架 里头去。这就是ASPX 你只要把你编译好的网站放到IIS中就可以提供服务了。 而我们的 SOCKET框架 相当于IIS, 已经提供了 。NET 网络通讯的 一些基本功能,在此功能上你只要写好数据处理方式 就可以完成一个网络服务端程序了。 这就相当于写ASPX 从来不用去理解低层的SOCKET 通讯
好的下面 就让我们开始吧
要实现 SOKCET通讯 我们必须要 有SOCKET 服务器端类, 此类必须要有非常好的性能 以及 稳定性 ,并且提供良好的 调用方式 处理方式。
第一章 SOCKET服务器类
。NET SOCKET 里面 Begin 函数提供了异步 方法,但是 此方法 还是过于复杂 以及无法达到 最好的性能。
我们采用。NET 3.5 里面的新提供的 XXXAsync 系列的函数。 此类函数提供 基于IOCP 的SOCKET服务, 传说能带动 5W个连接以上。 当然这个5W个我没有试过。但是使用 ASYNC 我们可以使用 SocketAsyncEventArgs 方便的 处理数据以及 确认数据包对象(此数据包是哪个用户发过来的) 也许有的人会说 哎呀3。5很大啊 我没装3。5啊。 我这里和你说 你写的是服务器 服务器上没3。5装下就好了。而客户端呢最好用。NET 2。0或者C++ 写。 为什么呢 方便大家安装啊
好的不废话 我发出代码来
SOKCET 对象我就不说了
说下 下面4个函数 我已经注释了 我只说下为什么要定义。 这就好比使用 异步SOKCET一样 必须要有回调函数。 而在3。5新加的 异步处理中 事件代理了 回调函数 所以我们必须定义事件 ,也许你会说 我们可以在 设置时间处理的时候定义。 当然也可以,但是这是服务器
所以还是先定义的好。关键还是性能麻!
继续贴代码
在类外面实现3个代理
3个代理 表示什么 上面写的很清楚 。 为什么要定义呢 因为 通常 数据处理方法 都在SOKCET服务类 的外面 所以需要代理拉 来把 方法引入
在类里面定义3个 代理的对象
现在也许你还不明白 SOCKET 异步处理都是基于 SocketAsyncEventArgs 对象的 需要大量的 SocketAsyncEventArgs 对象
所以我们需要事先 定义好 大量的 SocketAsyncEventArgs 对象 这样就不必在需要是创建 而消耗CPU 。所以我们定义 一个 Queue<SocketAsyncEventArgs> 来保存 SocketAsyncEventArgs 对象。 使用的时候只要
SocketAsyncEventArgs AcceptAsy = AysncQueue.Dequeue(); 就OK了 这比新创建一个明显速度要快
不废话贴代码
你SOCKET 服务器 通讯必须要有把 客户端 连接 收集在一起,不然你如何知道 你程序有多少个SOCKET客户端连接 如何调用指定客户呢?
我采用 LIST<SOCKET> 来保存
添加些必要的属性
下面实现 构造函数 一些 元素的初始化 以及定义
这里补充下:
for (int i = 0; i < ListCout; i++)
{
SocketAsyncEventArgs e = new SocketAsyncEventArgs();
AysncQueue.Enqueue(e);
}
一般 一个 SocketAsyncEventArgs对象对应一个用户连接 至少这样设置可以提供性能。所以这里列队到小等于 最大连接数是有必要的。如果万一 数量不够 还可以另创建
继续贴代码
除了 SetAcceptAsy() 其他4个函数对应
/// <summary>
/// 连接传入所处理的函数代理
/// </summary>
private EventHandler<SocketAsyncEventArgs> AcceptAsyCompleted { get; set; }
/// <summary>
/// 读取客户端数据的函数代理
/// </summary>
private EventHandler<SocketAsyncEventArgs> ReceiveCompleted { get; set; }
/// <summary>
/// 发送数据的函数代理
/// </summary>
private EventHandler<SocketAsyncEventArgs> SendCompleted { get; set; }
/// <summary>
/// 断开客户端处理的函数代理
/// </summary>
private EventHandler<SocketAsyncEventArgs> DisconnectCompleted { get; set; }
这4个代理的 函数处理
这4个函数里面拥有 SocketAsyncEventArgs 的使用方法 下面我将一步步的去说明
SetAcceptAsy() 方法主要是获取一个 SocketAsyncEventArgs 对象 然后 将此对象 放入SOCKET AcceptAsync 函数让他进行监听
当然在监听前必须要设置 监听处理的事件
AcceptAsy.Completed += AcceptAsyCompleted;
我才此函数中加入了 SocketAsyncEventArgs 对象列队数量检测和连接数检测 这是必要了为了避免错误
AcceptAsy_Completed 函数是 SetAcceptAsy() 为对象设置的事件处理
因为我的SOCKET 服务器类 实现了 接口IDisposable 所以在方法的一开头 就检测 此 类是否被Disposed 掉 如果我的SOCKET 服务器类 调用了Disposed() 后 再次调用此事件时不做处理 并且将此 环境的 SocketAsyncEventArgs 对象 Disposed掉
Socket client = e.AcceptSocket; //获取 当前客户端的SOCKET 对象
e.Completed -= AcceptAsy_Completed;
e.Completed += ReceiveCompleted; //把 SocketAsyncEventArgs 对象 的事件处理更改为读取数据包
byte[] buff = new byte[MaxByteCout];
e.SetBuffer(buff, 0, buff.Length); //设置接收数据包
client.ReceiveAsync(e); //将e 放入SOCKET 的 ReceiveAsync 方法
if (!clientlist.Contains(client)) //将此SOCKET 放入用户SOCKET列表
{
this.clientlist.Add(client);
}
else
{
CloseSocket(e);
}
if (Connetions != null) //如果 Connetions 代理不等于空 将E传递给 Connetions 代理 这样 你就能获得连接信息了
{
Connetions(e);
}
SetAcceptAsy(); //重新将一个SocketAsyncEventArgs 对象 用于监听
在 Receive_Completed 函数中
我们第一步检测的就是e.BytesTransferred 获取的数据包长度 如果 有长度那么说明 你接受到了数据包 如果没有为0 那么说明用户已经断开连接了
LocalAsyncQueue(); 函数是用来重新创建 一个 SocketAsyncEventArgs 列队
好的下面是最后3个函数 一个断开一个发送 以及重组 SocketAsyncEventArgs 列队
Socket 服务器类 就可以使用了
以下是完整代码:
我们将在下一章中 讲如何使用此 类进行网络开发