国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
C#使用SocketAsyncEventArgs操作套接字的簡單異步通訊

SocketAsyncEventArgs是一個套接字操作的類,主要作用是實現(xiàn)socket消息的異步接收和發(fā)送,跟Socket的BeginSend和
BeginReceive方法異步處理沒有多大區(qū)別,它的優(yōu)勢在于完成端口的實現(xiàn)來處理大數(shù)據(jù)的并發(fā)情況,由于本人學(xué)習(xí)不久,對千萬級的
數(shù)據(jù)訪問還沒有多大體會,這里的簡單實現(xiàn)作為一個學(xué)習(xí)的筆記,請酌情參考,如有錯誤,請及時指正。

先說說SockeAsyncEventArgs類的操作方法,以下是摘自MSDN的內(nèi)容(MSDN的SockeAsyncEventArgs類描述):

1、分配一個新的 SocketAsyncEventArgs 上下文對象,或者從應(yīng)用程序池中獲取一個空閑的此類對象。

1   SocketAsyncEventArgs saea = new SocketAsyncEventArgs();2   //或者(這里的SocketAsyncEventArgsPool類一般是自己實現(xiàn),MSDN有通過棧結(jié)構(gòu)實現(xiàn)的程序池,也可以使用隊列或鏈表):3   SocketAsyncEventArgs saea = new SocketAsyncEventArgsPool().Pop();

 

2、將該上下文對象的屬性設(shè)置為要執(zhí)行的操作(例如,完成回調(diào)方法、數(shù)據(jù)緩沖區(qū)、緩沖區(qū)偏移量以及要傳輸?shù)淖畲髷?shù)據(jù)量)。SocketAsyncEventArgs一般會根據(jù)操作執(zhí)行相同的回調(diào)函數(shù),所有設(shè)置內(nèi)容在不同操作的回調(diào)都可以訪問,我在調(diào)試時發(fā)現(xiàn)不能同時收發(fā)消息(可能是半雙工),因此使用接收和發(fā)送試用兩個對象

1   byte[] buffer = new byte[1024];2   saea.SetBuffer(buffer, 0, buffer.Length);    //設(shè)置緩沖區(qū)3   saea.Completed += new EventHandler<SocketAsyncEventArgs>(MethodName);    //設(shè)置回調(diào)方法4   saea.RemoteEndPoint = new IPEndPoint(IPAddress.Any,1234);    //設(shè)置遠端連接節(jié)點,一般用于接收消息5   saea.UserToken = new AsyncUserToken();     //設(shè)置用戶信息,一般把連接的Socket對象放在這里

 

3、調(diào)用適當(dāng)?shù)奶捉幼址椒?(xxxAsync) 以啟動異步操作。
4、如果異步套接字方法 (xxxAsync) 返回 true,則在回調(diào)中查詢上下文屬性來獲取完成狀態(tài)。
5、如果異步套接字方法 (xxxAsync) 返回 false,則說明操作是同步完成的。 可以查詢上下文屬性來獲取操作結(jié)果。

 1   //這是調(diào)用套接字的方法,即socket調(diào)用的方法: 2   Socket socket = saea.AcceptSocket; 3   socket.ConnectAsync(saea);     //異步進行連接 4   socket.AcceptAsync(saea);     //異步接收連接 5   socket.ReceiveAsync(saea);     //異步接收消息 6   socket.SendAsync(saea);     //異步發(fā)送消息 7   //這里注意的是,每個操作方法返回的是布爾值,這個布爾值的作用,是表明當(dāng)前操作是否有等待I/O的情況,如果返回false則表示當(dāng)前是同步操作,不需要等待,此時要要同步執(zhí)行回調(diào)方法,一般寫法是 8   bool willRaiseEvent = socket.ReceiveAsync(saea); //繼續(xù)異步接收消息 9   if (!willRaiseEvent)10   {11     MethodName(saea);12   }

 

6、將該上下文重用于另一個操作,將它放回到應(yīng)用程序池中,或者將它丟棄。
  如果用于持續(xù)監(jiān)聽連接,要注意saea.AcceptSocket = null;只有把saea對象的AcceptSocket置為null,才能監(jiān)聽到新的連接;
  如果只用于單次通訊,則在用完saea對象是可丟棄,saea.Dispose(),如果想重復(fù)利用,則設(shè)置相應(yīng)的異步操作即可,
  

1 saea.AcceptSocket = null;//重新監(jiān)聽    2 socket.ReceiveAsync(saea);//重新接收3 socket.SendAsync(saea);//重新發(fā)送

 

關(guān)于具體的實現(xiàn),類似于之前我記下的簡單Socket通信,先是SocketServerManager的實現(xiàn),該實現(xiàn)也是參考自MSDN:

  1     public class SocketServerManager  2     {  3         readonly Socket _socket;        //監(jiān)聽Socket  4         readonly EndPoint _endPoint;  5         private const int Backlog = 100;     //允許連接數(shù)目  6         private int byteSize = 64;  7   8         //同時UI界處理的事件  9         public delegate void OnEventCompletedHanlder(MessageFormat msg); 10         public event OnEventCompletedHanlder OnReceiveCompletedEvent; 11         public event OnEventCompletedHanlder OnSendCompletedEvent; 12         public event OnEventCompletedHanlder OnConnectedEvent; 13         public event OnEventCompletedHanlder OnDisconnectEvent; 14         public event OnEventCompletedHanlder OnNotConnectEvent; 15  16         //private BufferManager bufferManager;        //消息緩存管理 17         SocketAsyncEventArgsPool rwPool;              //SAEA池 18         private Semaphore maxClient; 19         private Dictionary<string, SocketAsyncEventArgs> dicSAEA = null;  20  21         public SocketServerManager(string ip, int port) 22         { 23             _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 24             IPAddress ipAddress = IPAddress.Parse(ip); 25             _endPoint = new IPEndPoint(ipAddress, port); 26             //bufferManager = new BufferManager(totalBytes, byteSize); 27             maxClient = new Semaphore(Backlog, Backlog); 28             Init(); 29         } 30  31         public void Init() 32         { 33             //bufferManager.InitBuffer(); 34             SocketAsyncEventArgs rwEventArgs; 35             rwPool = new SocketAsyncEventArgsPool(Backlog); 36             dicSAEA = new Dictionary<string, SocketAsyncEventArgs>(); 37             for (int i = 0; i < 100; i++) 38             { 39                 rwEventArgs = new SocketAsyncEventArgs(); 40                 rwEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); 41                rwEventArgs.UserToken = new AsyncUserToken(); 42  43                 rwEventArgs.SetBuffer(new byte[byteSize],0,byteSize); 44                 //bufferManager.SetBuffer(rwEventArgs); 45  46                 rwPool.Push(rwEventArgs); 47             } 48         } 49  50         /// <summary> 51         /// 開啟Socket監(jiān)聽 52         /// </summary> 53         public void Start() 54         { 55             _socket.Bind(_endPoint);        //綁定本地地址進行監(jiān)聽 56             _socket.Listen(Backlog);        //設(shè)置監(jiān)聽數(shù)量 57  58             StartAccept(null); 59         } 60  61         public void StartAccept(SocketAsyncEventArgs acceptEventArg) 62         { 63             if (acceptEventArg == null) 64             { 65                 acceptEventArg = new SocketAsyncEventArgs(); 66                 acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnectedCompleted); 67             } 68             else 69             { 70                 acceptEventArg.AcceptSocket = null; 71             } 72  73             maxClient.WaitOne(); 74             bool willRaiseEvent = _socket.AcceptAsync(acceptEventArg); 75             if (!willRaiseEvent) 76             { 77                 ProcessAccept(acceptEventArg); 78             } 79         } 80  81         private void ProcessAccept(SocketAsyncEventArgs e) 82         { 83             if (e.SocketError != SocketError.Success) return;       //異步處理失敗,不做處理 84             SocketAsyncEventArgs saea = rwPool.Pop(); 85             AsyncUserToken token = saea.UserToken as AsyncUserToken; 86             token.UserSocket = e.AcceptSocket;       //獲取遠端對話Socket對象 87             string ipRemote = token.UserSocket.RemoteEndPoint.ToString(); 88             string ip = token.UserSocket.RemoteEndPoint.ToString(); 89             MessageFormat msg = new MessageFormat(string.Format("遠程地址[{0}]成功連接到本地", ipRemote), ip, MsgType.Empty); 90             msg.tag = MsgType.Empty; 91             if (OnConnectedEvent != null) OnConnectedEvent(msg);            //調(diào)用UI方法處理 92  93             //連接成功后,發(fā)送消息通知遠程客戶端 94             //OnSend("Connected Success !", _sendSocket.RemoteEndPoint); 95             SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs(); 96             sendArgs.RemoteEndPoint = token.UserSocket.RemoteEndPoint; 97             sendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); 98             sendArgs.UserToken = saea.UserToken; 99             dicSAEA.Add(token.UserSocket.RemoteEndPoint.ToString(), sendArgs);100             bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(saea);101             if (!willRaiseEvent)102             {103                 OnReceiveCompleted(saea);104             }105 106             StartAccept(e);107         }108 109         /// <summary>110         /// 遠端地址連接本地成功的回調(diào)111         /// </summary>112         /// <param name="sender"></param>113         /// <param name="e"></param>114         public void OnConnectedCompleted(object sender, SocketAsyncEventArgs e)115         {116             ProcessAccept(e);117         }118 119         public void IO_Completed(object sender, SocketAsyncEventArgs e)120         {121             switch (e.LastOperation)122             {123                 case SocketAsyncOperation.Receive:124                     OnReceiveCompleted(e);125                     break;126                 case SocketAsyncOperation.Send:127                     OnSendCompleted(e);128                     break;129                 default:130                     throw new ArgumentException("The last operation completed on the socket was not a receive or send");131             }   132         }133 134         /// <summary>135         /// 執(zhí)行異步發(fā)送消息136         /// </summary>137         /// <param name="msg">消息內(nèi)容</param>138         /// <param name="ip">發(fā)送遠端地址</param>139         public void OnSend(MessageFormat mf)140         {141             if (!dicSAEA.ContainsKey(mf.ipStr))142             {143                 if (OnNotConnectEvent != null)144                 {145                     OnNotConnectEvent(new MessageFormat("不存在此連接客戶端","",MsgType.Empty));146                     return;147                 }148             }149             SocketAsyncEventArgs saea = dicSAEA[mf.ipStr];150             AsyncUserToken token = saea.UserToken as AsyncUserToken;151             if (saea == null) return;152             //saea.SetBuffer(sendBuffer, 0, sendBuffer.Length);  //設(shè)置SAEA的buffer消息內(nèi)容153             byte[] sendBuffer = Encoding.Unicode.GetBytes(string.Format("[length={0}]{1}", mf.msgStr.Length, mf.msgStr));154             saea.SetBuffer(sendBuffer, 0, sendBuffer.Length);155             bool willRaiseEvent = token.UserSocket.SendAsync(saea);156             if (!willRaiseEvent)157             {158                 OnSendCompleted(saea);159             }160         }161 162         /// <summary>163         /// 發(fā)送消息回調(diào)處理164         /// </summary>165         /// <param name="sender"></param>166         /// <param name="e"></param>167         public void OnSendCompleted(SocketAsyncEventArgs e)168         {169             AsyncUserToken token = e.UserToken as AsyncUserToken;170             byte[] sendBuffer = e.Buffer;171             string msgStr = Encoding.Unicode.GetString(sendBuffer);172             string ipAddress = token.UserSocket.RemoteEndPoint.ToString();173             MessageFormat msg = new MessageFormat(msgStr, ipAddress, MsgType.Send);174             if (OnSendCompletedEvent != null) OnSendCompletedEvent(msg);        //調(diào)用UI方法處理175         }176 177         /// <summary>178         /// 接收消息回調(diào)處理179         /// </summary>180         /// <param name="e"></param>181         public void OnReceiveCompleted(SocketAsyncEventArgs e)182         {183             if (e.SocketError != SocketError.Success) return;   //判斷消息的接收狀態(tài)184             AsyncUserToken token = e.UserToken as AsyncUserToken;185             int lengthBuffer = e.BytesTransferred;      //獲取接收的字節(jié)長度186             string ipAddress = token.UserSocket.RemoteEndPoint.ToString();187             MessageFormat msg = new MessageFormat();188             //如果接收的字節(jié)長度為0,則判斷遠端服務(wù)器關(guān)閉連接189             if (lengthBuffer <= 0)190             {191                 msg.msgStr = "遠端服務(wù)器已經(jīng)斷開連接";192                 msg.ipStr = ipAddress;193                 msg.tag = MsgType.Handler;194                 if (OnDisconnectEvent != null) OnDisconnectEvent(msg);195                 CloseClientSocket(e);196             }197             else198             {199                 byte[] receiveBuffer = e.Buffer;200                 byte[] buffer = new byte[lengthBuffer];201                 Buffer.BlockCopy(receiveBuffer, 0, buffer, 0, lengthBuffer);202                 msg.msgStr = Encoding.Unicode.GetString(buffer);203                 msg.ipStr = ipAddress;204                 msg.tag = MsgType.Receive;205                 bool willRaiseEvent = token.UserSocket.ReceiveAsync(e);     //繼續(xù)異步接收消息206                 if (!willRaiseEvent)207                 {208                     OnReceiveCompleted(e);209                 }210                 if (OnReceiveCompletedEvent != null) OnReceiveCompletedEvent(msg);        //調(diào)用UI方法處理211             }212         }213 214         private void CloseClientSocket(SocketAsyncEventArgs e)215         {216             AsyncUserToken token = e.UserToken as AsyncUserToken;217             try218             {219                 token.UserSocket.Shutdown(SocketShutdown.Send);220             }221             catch (Exception) { }222             dicSAEA.Remove(token.UserSocket.RemoteEndPoint.ToString());223             token.UserSocket.Close();224 225             maxClient.Release();226             rwPool.Push(e);227         }228     }

 

通過一個棧結(jié)構(gòu)SocketAsyncEventArgsPool保存的SocketAsyncEventArgs對象是用于接收消息,為了做到雙方通訊,我每次在接收到遠端客戶端連接時,就創(chuàng)建一個新的SocketAsyncEventArgs對象保存在Dictionary結(jié)構(gòu)中,這樣在消息發(fā)送是就可以根據(jù)Ip來發(fā)送給遠程客戶端。

 

客戶端的實現(xiàn)比較簡單,不用考慮多方的通訊:

  1     public class SocketClientManager  2     {  3         readonly Socket _socket;      //用于消息交互的socket對象  4         readonly EndPoint _endPoint;      //遠端地址  5         readonly SocketAsyncEventArgs _saea;        //處理連接和接收SAEA對象  6         //處理發(fā)送的SAEA處理,由于綁定不同的回調(diào)函數(shù),因此需要不同的SAEA對象  7         SocketAsyncEventArgs _sendSaea;           8   9         //處理UI的事件 10         public delegate void OnEventCompletedHanlder(MessageFormat msgFormat); 11         public event OnEventCompletedHanlder OnConnectedEvent;       //連接成功事件 12         public event OnEventCompletedHanlder OnReceiveCompletedEvent;        //收到消息事件 13         public event OnEventCompletedHanlder OnSendCompletedEvent;       //發(fā)送成功事件 14  15         public SocketClientManager(string ip, int port) 16         { 17             _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 18             IPAddress ipAddress = IPAddress.Parse(ip); 19             _endPoint = new IPEndPoint(ipAddress, port); 20             _saea = new SocketAsyncEventArgs {RemoteEndPoint = _endPoint}; 21         } 22  23         /// <summary> 24         /// 開啟進行遠程連接 25         /// </summary> 26         public void Start() 27         { 28             _saea.Completed += OnConnectedCompleted; 29             _socket.ConnectAsync(_saea);        //進行異步連接 30  31         } 32  33         /// <summary> 34         /// 連接成功的事件回調(diào)函數(shù) 35         /// </summary> 36         /// <param name="sender"></param> 37         /// <param name="e"></param> 38         public void OnConnectedCompleted(object sender, SocketAsyncEventArgs e) 39         { 40             if (e.SocketError != SocketError.Success) return; 41             Socket socket = sender as Socket; 42             string ipRemote = socket.RemoteEndPoint.ToString(); 43             MessageFormat messageFormat = new MessageFormat(string.Format("連接服務(wù)器[{0}]成功!", ipRemote), socket.LocalEndPoint.ToString(), MsgType.Empty); 44             if (OnConnectedEvent != null) OnConnectedEvent(messageFormat); 45  46             //開啟新的接受消息異步操作事件 47             var receiveSaea = new SocketAsyncEventArgs(); 48             var receiveBuffer = new byte[1024 * 4]; 49             receiveSaea.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);       //設(shè)置消息的緩沖區(qū)大小 50             receiveSaea.Completed += OnReceiveCompleted;         //綁定回調(diào)事件 51             receiveSaea.RemoteEndPoint = _endPoint; 52             _socket.ReceiveAsync(receiveSaea); 53         } 54  55         /// <summary> 56         /// 接受消息的回調(diào)函數(shù) 57         /// </summary> 58         /// <param name="sender"></param> 59         /// <param name="e"></param> 60         public void OnReceiveCompleted(object sender, SocketAsyncEventArgs e) 61         { 62             if (e.SocketError == SocketError.OperationAborted) return; 63             var socket = sender as Socket; 64             MessageFormat messageFormat = new MessageFormat(); 65             if (e.SocketError == SocketError.Success &&e.BytesTransferred > 0) 66             { 67                 string ipAddress = socket.RemoteEndPoint.ToString(); 68                 int lengthBuffer = e.BytesTransferred; 69                 byte[] receiveBuffer = e.Buffer; 70                 byte[] buffer = new byte[lengthBuffer]; 71                 Buffer.BlockCopy(receiveBuffer, 0, buffer, 0, lengthBuffer); 72                 messageFormat.msgStr = Encoding.Unicode.GetString(buffer); 73                 messageFormat.ipStr = ipAddress; 74                 messageFormat.tag = MsgType.Receive;; 75                 socket.ReceiveAsync(e); 76             } 77             else if (e.SocketError == SocketError.ConnectionReset && e.BytesTransferred == 0) 78             { 79                 messageFormat.msgStr = "服務(wù)器已經(jīng)斷開連接"; 80                 messageFormat.ipStr = socket.RemoteEndPoint.ToString(); 81                 messageFormat.tag = MsgType.Handler; 82             } 83             else 84             { 85                 return; 86             } 87             if (OnReceiveCompletedEvent != null) OnReceiveCompletedEvent(messageFormat); 88         } 89  90         /// <summary> 91         /// 發(fā)送消息回調(diào)函數(shù) 92         /// </summary> 93         /// <param name="sender"></param> 94         /// <param name="e"></param> 95         public void OnSendCompleted(object sender, SocketAsyncEventArgs e) 96         { 97             if (e.SocketError != SocketError.Success) return; 98             var socket = sender as Socket; 99             byte[] sendBuffer = e.Buffer;100             MessageFormat messageFormat = new MessageFormat(Encoding.Unicode.GetString(sendBuffer),socket.RemoteEndPoint.ToString(),MsgType.Send);101             if (OnSendCompletedEvent != null) OnSendCompletedEvent(messageFormat);102         }103 104         /// <summary>105         /// 斷開連接106         /// </summary>107         public void OnDisConnect()108         {109             if (_socket != null)110             {111                 try112                 {113                     _socket.Shutdown(SocketShutdown.Both);114                 }115                 catch (SocketException ex)116                 {117                 }118                 finally119                 {120                     _socket.Close();121                 }122             }123         }124 125         /// <summary>126         /// 發(fā)送消息127         /// </summary>128         /// <param name="msg"></param>129         public void SendMsg(MessageFormat mf)130         {131             byte[] sendBuffer = Encoding.Unicode.GetBytes(string.Format("[length={0}]{1}", mf.msgStr.Length, mf.msgStr));132             if (_sendSaea == null)133             {134                 _sendSaea = new SocketAsyncEventArgs {RemoteEndPoint = _endPoint};135                 _sendSaea.Completed += OnSendCompleted;136             }137             _sendSaea.SetBuffer(sendBuffer, 0, sendBuffer.Length);138             if (_socket != null) _socket.SendAsync(_sendSaea);139         }140     }

 

同樣是使用收發(fā)不同的SocketAsyncEventArgs對象。

 

另外,關(guān)于解決緩存容量不足以容納一條消息的半包問題,這里使用了簡單的字符處理類,這個類是復(fù)制自Jimmy Zhang的類RequestHandler,當(dāng)然,方法還是不完善的,難以解決不同順序的消息接受。


具體源碼(.net4.5,vs2013):具體源碼 http://files.cnblogs.com/files/supheart/ServerBySocket.zip

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
深入探析c# Socket
SocketAsyncEventArgs使用解說
高性能Socket設(shè)計實現(xiàn) - 志良的技術(shù)博客 - 博客園
Socket連接池
C#高性能 TCP 服務(wù)的多種實現(xiàn)方式
C#高性能TCP服務(wù)的多種實現(xiàn)方式
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服