.net 3.5平臺(tái)上的Socket開發(fā)其實(shí)這篇文章在一年前就應(yīng)該寫了,不過(guò)一直覺得自己沒(méi)空,一拖就拖到現(xiàn)在。先對(duì)大家說(shuō)句對(duì)不起了。 在之前的文章中,我們講了如何在.NET 2.0下面開發(fā)Socket項(xiàng)目。其中的異步Socket讓我們得以很輕松的在.NET中開發(fā)高性能服務(wù)端應(yīng)用。 但是,在實(shí)際應(yīng)用中我們還是發(fā)現(xiàn)了一些問(wèn)題的存在,如:我們?cè)诿恳淮尾僮鞯倪^(guò)程中都要?jiǎng)?chuàng)建一個(gè)IAsyncResult上下文對(duì)象,如果數(shù)據(jù)通訊很頻繁的話,會(huì)導(dǎo)致大量的IAsyncResult對(duì)象被創(chuàng)建,大大的增加了垃圾回收器的工作量,從而降低了整個(gè)應(yīng)用的效率。 在.NET 3.5中,這個(gè)麻煩已經(jīng)被解決了,在3.5 版本中,Socket定義了一些新的方法。這些方法不要求每一次操作都創(chuàng)建一個(gè)新的上下文對(duì)象。 如,在2.0中我們采用下面的方式在Socket上啟動(dòng)一次接收操作。3.5中我們可以用新的方法完成一次接收操作。 void ReceiveCallBack(IAsyncResult ar){} IAsyncResult result=socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ReceiveCallBack, info);//在這里有一個(gè)IAsyncResult對(duì)象被創(chuàng)建。 在 void OnReceiveCompleted(object sender,SocketAsyncEventArgs e){} SocketAsyncEventArgs receive=new SocketAnyncEventArgs(); receive.Completed+= OnReceiveCompleted; receive.SetBuffer(buffer,0,buffer.Length); socket.ReceiveAsync(receive); 在這里我們可以看出3.5 和 2.0 的一個(gè)明顯區(qū)別,那就是不是使用IAsyncResult而是用SocketAsyncEventArgs作為上下文對(duì)象。應(yīng)用程序創(chuàng)建并管理(并且可以重復(fù)使用)SocketAsyncEventArgs 對(duì)象。套接字操作的所有參數(shù)都由 SocketAsyncEventArgs 對(duì)象的屬性和方法指定。完成狀態(tài)也由 SocketAsyncEventArgs 對(duì)象的屬性提供。最后,需要使用事件處理程序回調(diào)完成方法。 讓我們來(lái)看看代碼: 首先我們創(chuàng)建一個(gè)用戶類,用來(lái)存儲(chǔ)和客戶端有關(guān)的數(shù)據(jù): public class UserObject { /// <summary> /// 接收數(shù)據(jù)的緩沖區(qū) /// </summary> public byte[] ReceiveBuffer { get; private set; } /// <summary> /// 發(fā)送數(shù)據(jù)的緩沖區(qū) /// </summary> public byte[] SendBuffer { get; private set; } /// <summary> /// 客戶端Socket對(duì)象 /// </summary> public Socket Socket { get; private set; } /// <summary> /// 發(fā)送數(shù)據(jù)上下文對(duì)象 /// </summary> public SocketAsyncEventArgs SendEventArgs { get; private set; } /// <summary> /// 接收數(shù)據(jù)上下文對(duì)象 /// </summary> public SocketAsyncEventArgs ReceiveEventArgs { get; private set; } public UserObject(Socket socket) { ReceiveBuffer = new byte[1024];//定義接收緩沖區(qū) SendBuffer = new byte[1024];//定義發(fā)送緩沖區(qū) this.Socket = socket; SendEventArgs = new SocketAsyncEventArgs(); SendEventArgs.UserToken = this; ReceiveEventArgs = new SocketAsyncEventArgs(); ReceiveEventArgs.UserToken = this; ReceiveEventArgs.SetBuffer(ReceiveBuffer, 0, ReceiveBuffer.Length);//設(shè)置接收緩沖區(qū) SendEventArgs.SetBuffer(SendBuffer, 0, SendBuffer.Length);//設(shè)置發(fā)送緩沖區(qū) } } 接下來(lái)我們開始接入客戶端連接: 1socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 2socket.Bind(localEP); 3socket.Listen(100); 4Console.WriteLine("Server is bind on {0}",socket.LocalEndPoint); 5acceptEventArgs = new SocketAsyncEventArgs();//創(chuàng)建接入Socket上下文對(duì)象 6acceptEventArgs.Completed += acceptCompleted;//注冊(cè)接入完成事件處理程序 7socket.AcceptAsync(acceptEventArgs);//投遞接入操作 8Console.WriteLine("Server is started"); 9 10//接入事件處理程序 11void acceptCompleted(object sender, SocketAsyncEventArgs e) 12{ 13 var client = new UserObject( e.AcceptSocket);//創(chuàng)建用戶對(duì)象實(shí)例 14 client.ReceiveEventArgs.Completed += Receives_Completed;//注冊(cè)接收數(shù)據(jù)完成事件處理程序 15 client.SendEventArgs.Completed += Send_Completed;//注冊(cè)發(fā)送數(shù)據(jù)完成事件處理程序 16 client.Socket.ReceiveAsync(client.ReceiveEventArgs);//投遞接收數(shù)據(jù)操作 17} 好了,我們開始接收數(shù)據(jù): 1//接收數(shù)據(jù)完成事件處理程序 2void Receives_Completed(object sender, SocketAsyncEventArgs e) 3{ 4 var client = e.UserToken as UserObject; 5 if (e.BytesTransferred == 0)//如果傳輸?shù)臄?shù)據(jù)量為0,則表示鏈接已經(jīng)斷開 6 { 7 Console.WriteLine("Socket:{0} is closed",client.Socket.Handle); 8 client.Socket.Close(); 9 } 10 else 11 { 12 string message = Encoding.Unicode.GetString(e.Buffer, 0, e.BytesTransferred);//獲取接收到的數(shù)據(jù) 13 Console.WriteLine("Socket:{0} send message:{1}",client.Socket.Handle,message); 14 string sent=string.Format("{0} bytes has been received",e.BytesTransferred); 15 int length = Encoding.Unicode.GetBytes(sent,0,sent.Length,client.SendBuffer,0);//將數(shù)據(jù)寫入發(fā)送緩沖區(qū) 16 client.SendEventArgs.SetBuffer(0, length);//設(shè)置緩沖區(qū)中有效數(shù)據(jù)的偏移量和長(zhǎng)度 17 client.Socket.SendAsync(client.SendEventArgs);//投遞發(fā)送數(shù)據(jù)操作 18 client.Socket.ReceiveAsync(client.ReceiveEventArgs);//投遞接收數(shù)據(jù)操作 19 } 20} 21 22//發(fā)送數(shù)據(jù)完成事件處理程序 23void Send_Completed(object sender, SocketAsyncEventArgs e) 24{ 25 var client = e.UserToken as UserObject; 26 if (e.BytesTransferred==0)//如果傳輸?shù)臄?shù)據(jù)量為0,則表示鏈接已經(jīng)斷開 27 { 28 Console.WriteLine("Socket:{0} is closed", client.Socket.Handle); 29 client.Socket.Close(); 30 } 31 else 32 { 33 Console.WriteLine("Sent {0} bytes data to socket:{1}",e.BytesTransferred, client.Socket.Handle); 34 } 35} 示例代碼在:http://files.cnblogs.com/wzd24/ConsoleApplication2.rar |
|
來(lái)自: 網(wǎng)文收集 > 《我的圖書館》