如何使用SocketAsyncEventArgs类
2014-12-16 · 知道合伙人数码行家
知道合伙人数码行家
向TA提问 私信TA
由于减少了阻塞线程,高性能I/O限制应用中广泛使用异步编程模型(AMP,Asynchronous Programming Model)。.NET Framework第一个版本就实现了APM,现在使用诸如lambda表达式等新的技术C#3.0一直在改进其性能。针对Socket编程,不仅性能上 提升了不少,而且新APM模型发布了一个更简易的编程方法,该方法使用SocketAsyncEventArgs类来保持I/O操作之间的上下文,从而降低对象分配和垃圾收集工作。
在.NET 2.0 SP1上可以使用SocketAsyncEventArgs类,本文的代码就是用Microsoft Visual Studio .NET 2005编写的。
使用代码
从SocketAsyncEventArgs类开始,我学习了MSDN上 的样例程序,但该文缺少一些内容:AsyncUserToken类。我认为这个类应该公开一个Socket属性,它对应执行I/O操作的Socket。一 段时间后,我认识到这个类不是必要的,因为属性UserToken是一个Object,它可以接受任何东西。下面的修改方法中直接使用一个Socket实 例当作UserToken。
我修改了如何操作侦听者收到消息的代码——不是简单地回发给客户端(参见ProcessReceive方法)。在样例程序中,我使用属性Buffer、Offset与BytesTransfered来接收消息,SetBuffer方法把修改后的消息回返给客户端。 为了控制侦听者生存期时间,使用了一个Mutex类的实例。基于原Init方法的Start方法创建Mutex对象,相应的Stop方法释放Mutex对象。这些方法适用于实现作为Windows服务的Socket服务器。
现在,我们有了一个Socket服务器,下一步使用SocketAsyncEventArgs类建立一个Socket客户端。虽然MSDN说这个类特别设计给网络服务器应用,但也没有限制在客户端代码中使用APM。下面给出了SocketClient类的样例代码:
// 失败时关闭Socket,根据SocketError抛出异常。
private void ProcessError(SocketAsyncEventArgs e)
{
Socket s = e.UserToken as Socket;
if (s.Connected)
{
// 关闭与客户端关联的Socket
try
{
s.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
// 如果客户端处理已经关闭,抛出异常
}
finally
{
if (s.Connected)
{
s.Close();
}
}
}
// 抛出SocketException
throw new SocketException((Int32)e.SocketError);
}
// 与主机交换消息。
internal String SendReceive(String message)
{
if (connected)
{
// 创建一个发送缓冲区。
Byte [] sendBuffer = Encoding.ASCII.GetBytes(message);
// 准备发送/接收操作的参数。
SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
completeArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
completeArgs.UserToken = clientSocket;
completeArgs.RemoteEndPoint = hostEndPoint;
completeArgs.Completed +=
new EventHandler<socketasynceventargs>(OnSend);
// 开始异步发送。
clientSocket.SendAsync(completeArgs);
// 等待发送/接收完成。
AutoResetEvent.WaitAll(autoSendReceiveEvents);
// 从SocketAsyncEventArgs缓冲区返回数据。
return Encoding.ASCII.GetString(completeArgs.Buffer,
completeArgs.Offset, completeArgs.BytesTransferred);
}
else
{
throw new SocketException((Int32)SocketError.NotConnected);
}
}
#region IDisposable Members
// 释放SocketClient实例。
public void Dispose()
{
autoConnectEvent.Close();
autoSendReceiveEvents[SendOperation].Close();
autoSendReceiveEvents[ReceiveOperation].Close();
if (clientSocket.Connected)
{
clientSocket.Close();
}
}
#endregion
}
} 转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦