.net 3.5平台上的Socket开发

其实这篇文章在一年前就应该写了,不过一直觉得自己没空,一拖就拖到现在。先对大家说句对不起了。

在之前的文章中,我们讲了如何在.NET 2.0下面开发Socket项目。其中的异步Socket让我们得以很轻松的在.NET中开发高性能服务端应用。

但是,在实际应用中我们还是发现了一些问题的存在,如:我们在每一次操作的过程中都要创建一个IAsyncResult上下文对象,如果数据通讯很频繁的话,会导致大量的IAsyncResult对象被创建,大大的增加了垃圾回收器的工作量,从而降低了整个应用的效率。

.NET 3.5中,这个麻烦已经被解决了,在3.5 版本中,Socket定义了一些新的方法。这些方法不要求每一次操作都创建一个新的上下文对象。

如,在2.0中我们采用下面的方式在Socket上启动一次接收操作。3.5中我们可以用新的方法完成一次接收操作。

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->voidReceiveCallBack(IAsyncResultar){}
IAsyncResultresult
=socket.BeginReceive(info.Buffer,0,info.Buffer.Length,SocketFlags.None,ReceiveCallBack,info);//在这里有一个IAsyncResult对象被创建。

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->voidOnReceiveCompleted(objectsender,SocketAsyncEventArgse){}
SocketAsyncEventArgsreceive
=newSocketAnyncEventArgs();
receive.Completed
+=OnReceiveCompleted;
receive.SetBuffer(buffer,
0,buffer.Length);
socket.ReceiveAsync(receive);

在这里我们可以看出3.5 和 2.0 的一个明显区别,那就是不是使用IAsyncResult而是用SocketAsyncEventArgs作为上下文对象。应用程序创建并管理(并且可以重复使用)SocketAsyncEventArgs 对象。套接字操作的所有参数都由 SocketAsyncEventArgs 对象的属性和方法指定。完成状态也由 SocketAsyncEventArgs 对象的属性提供。最后,需要使用事件处理程序回调完成方法。

让我们来看看代码:

首先我们创建一个用户类,用来存储和客户端有关的数据:

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicclassUserObject
{
/**////<summary>
///接收数据的缓冲区
///</summary>

publicbyte[]ReceiveBuffer{get;privateset;}
/**////<summary>
///发送数据的缓冲区
///</summary>

publicbyte[]SendBuffer{get;privateset;}
/**////<summary>
///客户端Socket对象
///</summary>

publicSocketSocket{get;privateset;}
/**////<summary>
///发送数据上下文对象
///</summary>

publicSocketAsyncEventArgsSendEventArgs{get;privateset;}
/**////<summary>
///接收数据上下文对象
///</summary>

publicSocketAsyncEventArgsReceiveEventArgs{get;privateset;}

publicUserObject(Socketsocket)
{
ReceiveBuffer
=newbyte[1024];//定义接收缓冲区
SendBuffer=newbyte[1024];//定义发送缓冲区
this.Socket=socket;
SendEventArgs
=newSocketAsyncEventArgs();
SendEventArgs.UserToken
=this;
ReceiveEventArgs
=newSocketAsyncEventArgs();
ReceiveEventArgs.UserToken
=this;
ReceiveEventArgs.SetBuffer(ReceiveBuffer,
0,ReceiveBuffer.Length);//设置接收缓冲区
SendEventArgs.SetBuffer(SendBuffer,0,SendBuffer.Length);//设置发送缓冲区
}

}

接下来我们开始接入客户端连接:

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1socket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
2socket.Bind(localEP);
3socket.Listen(100);
4Console.WriteLine("Serverisbindon{0}",socket.LocalEndPoint);
5acceptEventArgs=newSocketAsyncEventArgs();//创建接入Socket上下文对象
6acceptEventArgs.Completed+=acceptCompleted;//注册接入完成事件处理程序
7socket.AcceptAsync(acceptEventArgs);//投递接入操作
8Console.WriteLine("Serverisstarted");
9
10//接入事件处理程序
11voidacceptCompleted(objectsender,SocketAsyncEventArgse)
12{
13varclient=newUserObject(e.AcceptSocket);//创建用户对象实例
14client.ReceiveEventArgs.Completed+=Receives_Completed;//注册接收数据完成事件处理程序
15client.SendEventArgs.Completed+=Send_Completed;//注册发送数据完成事件处理程序
16client.Socket.ReceiveAsync(client.ReceiveEventArgs);//投递接收数据操作
17}

好了,我们开始接收数据:

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1//接收数据完成事件处理程序
2voidReceives_Completed(objectsender,SocketAsyncEventArgse)
3{
4varclient=e.UserTokenasUserObject;
5if(e.BytesTransferred==0)//如果传输的数据量为0,则表示链接已经断开
6{
7Console.WriteLine("Socket:{0}isclosed",client.Socket.Handle);
8client.Socket.Close();
9}

10else
11{
12stringmessage=Encoding.Unicode.GetString(e.Buffer,0,e.BytesTransferred);//获取接收到的数据
13Console.WriteLine("Socket:{0}sendmessage:{1}",client.Socket.Handle,message);
14stringsent=string.Format("{0}byteshasbeenreceived",e.BytesTransferred);
15intlength=Encoding.Unicode.GetBytes(sent,0,sent.Length,client.SendBuffer,0);//将数据写入发送缓冲区
16client.SendEventArgs.SetBuffer(0,length);//设置缓冲区中有效数据的偏移量和长度
17client.Socket.SendAsync(client.SendEventArgs);//投递发送数据操作
18client.Socket.ReceiveAsync(client.ReceiveEventArgs);//投递接收数据操作
19}

20}

21
22//发送数据完成事件处理程序
23voidSend_Completed(objectsender,SocketAsyncEventArgse)
24{
25varclient=e.UserTokenasUserObject;
26if(e.BytesTransferred==0)//如果传输的数据量为0,则表示链接已经断开
27{
28Console.WriteLine("Socket:{0}isclosed",client.Socket.Handle);
29client.Socket.Close();
30}

31else
32{
33Console.WriteLine("Sent{0}bytesdatatosocket:{1}",e.BytesTransferred,client.Socket.Handle);
34}

35}

示例代码在:http://files.cnblogs.com/wzd24/ConsoleApplication2.rar

你可能感兴趣的:(socket)