程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .net 3.5平台上的Socket開發

.net 3.5平台上的Socket開發

編輯:關於.NET

在之前的文章中,我們講了如何在.NET 2.0下面開發Socket項目。其中的異步Socket讓我們得以很輕 松的在.NET中開發高性能服務端應用。

但是,在實際應用中我們還是發現了一些問題的存在,如:我們在每一次操作的過程中都要創建一個 IAsyncResult上下文對象,如果數據通訊很頻繁的話,會導致大量的IAsyncResult對象被創建,大大的增 加了垃圾回收器的工作量,從而降低了整個應用的效率。

在.NET 3.5中,這個麻煩已經被解決了,在3.5 版本中,Socket定義了一些新的方法。這些方法不要 求每一次操作都創建一個新的上下文對象。

如,在2.0中我們采用下面的方式在Socket上啟動一次接收操作。

void ReceiveCallBack(IAsyncResult ar){}
IAsyncResult result=socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ReceiveCallBack, info);//在這裡有一個IAsyncResult對象被創建。

在3.5中我們可以用新的方法完成一次接收操作。

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 的一個明顯區別,那就是不是使用IAsyncResult而是用 SocketAsyncEventArgs作為上下文對象。應用程序創建並管理(並且可以重復使用) SocketAsyncEventArgs 對象。套接字操作的所有參數都由 SocketAsyncEventArgs 對象的屬性和方法指 定。完成狀態也由 SocketAsyncEventArgs 對象的屬性提供。最後,需要使用事件處理程序回調完成方法 。

讓我們來看看代碼:

首先我們創建一個用戶類,用來存儲和客戶端有關的數據:

public class UserObject
    {
        /**//// <summary>
        /// 接收數據的緩沖區
        /// </summary>
        public byte[] ReceiveBuffer { get; private set; }
        /**//// <summary>
        /// 發送數據的緩沖區
        /// </summary>
        public byte[] SendBuffer { get; private set; }
        /**//// <summary>
        /// 客戶端Socket對象
        /// </summary>
        public Socket Socket { get; private set; }
        /**//// <summary>
        /// 發送數據上下文對象
        /// </summary>
        public SocketAsyncEventArgs SendEventArgs { get; private set; }
        /**//// <summary>
        /// 接收數據上下文對象
        /// </summary>
        public SocketAsyncEventArgs ReceiveEventArgs { get; private set; }

         public UserObject(Socket socket)
        {
            ReceiveBuffer = new byte[1024];//定義接收緩沖區
            SendBuffer = new byte[1024];//定義發送緩沖區
            this.Socket = socket;
            SendEventArgs = new SocketAsyncEventArgs();
            SendEventArgs.UserToken = this;
            ReceiveEventArgs = new SocketAsyncEventArgs();
            ReceiveEventArgs.UserToken = this;
            ReceiveEventArgs.SetBuffer(ReceiveBuffer, 0, ReceiveBuffer.Length);// 設置接收緩沖區
            SendEventArgs.SetBuffer(SendBuffer, 0, SendBuffer.Length);//設置發送 緩沖區
        }
}

接下來我們開始接入客戶端連接:

 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();//創建接入Socket上下文對象
 6acceptEventArgs.Completed += acceptCompleted;//注冊接入完成事件處理程序
 7socket.AcceptAsync(acceptEventArgs);//投遞接入操作
 8Console.WriteLine("Server is started");
 9
10//接入事件處理程序
11void acceptCompleted(object sender, SocketAsyncEventArgs e)
12{
13    var client = new UserObject( e.AcceptSocket);//創建用戶對象實例
14     client.ReceiveEventArgs.Completed += Receives_Completed;//注冊接收數據完成事件處 理程序
15     client.SendEventArgs.Completed += Send_Completed;//注冊發送數據完成事件處理程序
16     client.Socket.ReceiveAsync(client.ReceiveEventArgs);//投遞接收數據操作
17}

好了,我們開始接收數據:

 1//接收數據完成事件處理程序
 2void Receives_Completed(object sender, SocketAsyncEventArgs e)
 3{
 4    var client = e.UserToken as UserObject;
 5    if (e.BytesTransferred == 0)//如果傳輸的數據量為0,則表示鏈接已經斷開
 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);//獲取接收到的數據
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);//將數據寫入發送緩沖區
16         client.SendEventArgs.SetBuffer(0, length);//設置緩沖區中有效數據的偏移量 和長度
17         client.Socket.SendAsync(client.SendEventArgs);//投遞發送數據操作
18         client.Socket.ReceiveAsync(client.ReceiveEventArgs);//投遞接收數據操作
19    }
20}
21
22//發送數據完成事件處理程序
23void Send_Completed(object sender, SocketAsyncEventArgs e)
24{
25    var client = e.UserToken as UserObject;
26    if (e.BytesTransferred==0)//如果傳輸的數據量為0,則表示鏈接已經斷開
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}

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved