转自听香水榭] 一个封装的异步Socket客户端

一个封装的异步Socket客户端 

  1using System;
  2using System.Collections;
  3using System.Configuration;
  4using System.Net;
  5using System.Net.Sockets;
  6using System.Text;
  7
  8namespace Beijing.Traffic.Mobile.Net
  9{
 10    /**//// <summary>
 11    /// 智能手机端网络访问类
 12    /// </summary>

 13    public class MobileClient
 14    {
 15        //服务器IP地址
 16        private string serverIP;
 17        //服务器访问端口
 18        private string serverPort;
 19        private Socket socket;
 20        private byte [] buffer = new byte[256];
 21        private StringBuilder receiveData = null;
 22        private SocketEventArgs socketEventArgs = null
 23
 24        事件#region 事件
 25        //连接完成事件
 26        public event EventHandler OnConnect;        
 27        //接收完成事件 
 28        public event EventHandler OnReceivedFinshed;        
 29        //发送数据成功
 30        public event EventHandler OnSendFinished;        
 31        //产生异常时调用此事件
 32        public event EventHandler OnException;
 33
 34        #endregion
          
 35
 36        构造函数#region 构造函数
 37
 38        public MobileClient()
 39        {    
 40            this.serverIP = ConfigurationSettings.AppSettings["ServerIP"];
 41            this.serverPort = ConfigurationSettings.AppSettings["ServerPort"];
 42            receiveData = new StringBuilder();            
 43        }

 44        public MobileClient(string ip,string port)
 45        {
 46            this.serverIP = ip;
 47            this.serverPort = port;
 48            receiveData = new StringBuilder();
 49            
 50        }
        
 51        #endregion
    
 52
 53        private void UpdateEventMessage(string msg)
 54        {
 55            if( socketEventArgs == null)
 56            {
 57                socketEventArgs = new SocketEventArgs();
 58                socketEventArgs.ServerIP = this.serverIP;
 59                socketEventArgs.ServerPort = this.serverPort;
 60            }

 61            socketEventArgs.Message = msg;
 62
 63        }

 64
 65        /**//// <summary>
 66        /// 处理异常的事件
 67        /// </summary>
 68        /// <param name="msg"></param>

 69        private void  HandlerException(string msg)
 70        {
 71            if(OnException != null)
 72            {
 73                UpdateEventMessage(msg);                
 74                OnException(this,socketEventArgs);
 75
 76            }

 77            else
 78            {
 79                throw new Exception("异常处理事件不能为空");
 80            }

 81        }

 82
 83        连接远程服务器#region 连接远程服务器
 84
 85
 86        /**//// <summary>
 87        /// 异步连接远程服务器
 88        /// </summary>
 89        /// <returns></returns>

 90        public void Connect()
 91        {
 92            try
 93            {
 94                if( socket != null && socket.Connected )
 95                {
 96                    socket.Shutdown( SocketShutdown.Both );
 97                    System.Threading.Thread.Sleep( 10 );
 98                    socket.Close();
 99                }

100                socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );    
101
102                IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(serverIP),int.Parse(serverPort));
103                
104                socket.Blocking = false;                        
105                socket.BeginConnect( epServer, new AsyncCallback(Connected),socket );
106            }

107            catch(Exception ex)
108            {
109                this.Close();
110                this.HandlerException(ex.Message);
111            }

112        }

113
114        private void Connected( IAsyncResult ar )
115        {
116            try
117            {                
118                Socket sock = (Socket)ar.AsyncState;            
119                            
120                if( sock.Connected )
121                {
122                    if(OnConnect != null)
123                    {
124                        //连接成功事件                        
125                        UpdateEventMessage("连接远程服务器成功");
126                        OnConnect(this,socketEventArgs);
127                    }

128                }

129                else
130                {                    
131                    //连接失败事件                            
132                    this.HandlerException("连接远程服务器失败");
133                    
134                }

135            }

136            catch(Exception ex)
137            {
138                this.Close();
139                this.HandlerException(ex.Message);
140            }

141        }
        
142        #endregion

143
144        异步发送数据#region 异步发送数据
145
146        public void Send(string msg)
147        {        
148            byte[] msgBytes = Encoding.ASCII.GetBytes(msg);
149            Send(msgBytes);
150
151        }

152
153        public void Send(byte [] msgBytes)
154        {
155            try
156            {
157                ifthis.socket == null || !this.socket.Connected )
158                {
159                    throw new Exception("远程服务器没有连接,请先连接");
160                }

161                else
162                {
163                    AsyncCallback sendData = new AsyncCallback(SendCallback);
164                    this.socket.BeginSend(msgBytes,0,msgBytes.Length,SocketFlags.None,sendData,socket);
165                }

166            }

167            catch(Exception ex)
168            {
169                this.Close();
170                this.HandlerException(ex.Message);
171            }

172
173        }

174
175
176        private  void SendCallback(IAsyncResult ar) 
177        {
178            try 
179            {                
180                Socket client = (Socket) ar.AsyncState;                
181                int bytesSent = client.EndSend(ar);
182
183                if( bytesSent > 0)
184                {
185                    ifthis.OnSendFinished != null)
186                    {                        
187                        UpdateEventMessage("发送数据成功");
188                        OnSendFinished(this,socketEventArgs);
189                    }

190                }

191                else
192                {                                
193                    this.HandlerException("发送数据失败");                
194                }

195                
196            }
 
197            catch (Exception ex) 
198            {
199                this.Close();
200                this.HandlerException(ex.Message);
201            }

202        }

203
204
205        #endregion

206
207        异步接受数据#region 异步接受数据
208
209        public void Receive()
210        {
211            try
212            {
213                ifthis.socket == null || !this.socket.Connected )
214                {
215                    throw new Exception("远程服务器没有连接,请先连接");
216                }

217                else
218                {
219                    AsyncCallback recieveData = new AsyncCallback( OnReceiveData );
220                    socket.BeginReceive( buffer, 0, buffer.Length, SocketFlags.None, recieveData, socket );
221                }

222            }

223            catch( Exception ex )
224            {
225                this.Close();
226                this.HandlerException(ex.Message);
227            }

228        }

229
230
231        private void OnReceiveData(IAsyncResult ar)
232        {
233            Socket sock = (Socket)ar.AsyncState;
234            try
235            {
236                int nBytesRec = sock.EndReceive( ar );
237                if( nBytesRec > 0 )
238                {
239                    //接受数据并保存
240                    string sRecieved = Encoding.ASCII.GetString(buffer, 0, nBytesRec );
241                    receiveData.Append(sRecieved);
242                    Receive();
243                }

244                else
245                {                    
246                    sock.Shutdown( SocketShutdown.Both );
247                    sock.Close();
248                    if(receiveData.Length != 0)
249                    {
250                        if(OnReceivedFinshed != null)
251                        {                        
252                            UpdateEventMessage("接受数据成功");
253                            OnReceivedFinshed(this,socketEventArgs);
254                        }

255                    }

256                    else
257                    {                                                
258                        this.HandlerException("接受数据为空");                    
259                    }

260                }

261            }

262            catch( Exception ex )
263            {
264                this.Close();
265                this.HandlerException(ex.Message);
266            }

267        }

268
269
270        #endregion

271
272        接收到的数据#region 接收到的数据
273        /**//// <summary>
274        /// 接收到的数据
275        /// </summary>

276        public string ReceivedData
277        {
278            get
279            {
280                lock(this)
281                {
282                    return this.receiveData.ToString();
283                }

284            }

285        }

286
287        #endregion

288
289        关闭socket#region 关闭socket
290
291        public void Close()
292        {
293            try
294            {
295                if( socket != null && socket.Connected )
296                {
297                    socket.Shutdown( SocketShutdown.Both );
298                    System.Threading.Thread.Sleep( 10 );
299                    socket.Close();
300                }

301            }

302            catch(Exception ex)
303            {
304                this.HandlerException(ex.Message);
305            }

306        }

307
308        #endregion

309
310
311    }

312}

313

业务类在对此包装的socket进行访问时,由于是三个线程之间进行通讯,这个线程无法捕捉另一个线程产生的异常,所以通过信号量来通知是否有异常的产生:

  1#define TEST
  2
  3using System;
  4using System.Threading;
  5using System.Text;
  6using Beijing.Traffic.Mobile.Net;
  7
  8namespace Beijing.Traffic.Mobile.Bussiness
  9{
 10
 11    /**//// <summary>
 12    /// 业务逻辑的基类。
 13    /// </summary>

 14    public abstract class BussinessBase
 15    {
 16#if TEST
 17        //手机Socket客户端
 18        public MobileClient mobileClient = null;
 19        
 20#else
 21        protected MobileClient mobileClient = null;
 22#endif
 23        
 24        protected byte[] receicedBytes = null;
 25        //是否产生了Socket异常
 26        private bool hasException = false;
 27        //异常消息类
 28        private Exception socketException = null;
 29        
 30        //三个线程通知事件
 31        protected ManualResetEvent connectDone = new ManualResetEvent(false);
 32        protected ManualResetEvent sendDone = new ManualResetEvent(false);
 33        protected ManualResetEvent receiveDone = new ManualResetEvent(false);    
 34
 35        public BussinessBase()
 36        {            
 37        }

 38        /**//// <summary>
 39        /// 获取手机网络连接客户端类
 40        /// </summary>
 41        /// <returns></returns>

 42        public MobileClient GetMobileClient()
 43        {
 44            
 45            if(mobileClient == null)
 46            {
 47                mobileClient = new MobileClient("210.73.74.200","3333");
 48                mobileClient.OnConnect += new EventHandler(mobileClient_OnConnect);                
 49                mobileClient.OnSendFinished +=new EventHandler(mobileClient_OnSendFinished);
 50                mobileClient.OnReceivedFinshed +=new EventHandler(mobileClient_OnReceivedFinshed);
 51                mobileClient.OnException += new EventHandler(mobileClient_OnException);
 52            }

 53            return mobileClient;
 54        }

 55
 56
 57        事件#region 事件
 58        protected void mobileClient_OnConnect(object sender, System.EventArgs e)
 59        {
 60            this.connectDone.Set();
 61        }

 62        protected void mobileClient_OnException(object sender, System.EventArgs e)
 63        {
 64            SocketEventArgs socketEventArgs = e as SocketEventArgs;
 65            ChangeExceptionStatus(true);
 66            UpdateExceptionMessage(socketEventArgs.Message);
 67            this.connectDone.Set();            
 68        }

 69        protected void mobileClient_OnSendFinished(object sender, System.EventArgs e)
 70        {
 71            ChangeExceptionStatus(false);
 72            this.sendDone.Set();
 73        }

 74        protected void mobileClient_OnReceivedFinshed(object sender, System.EventArgs e)
 75        {
 76            ChangeExceptionStatus(false);
 77            this.receiveDone.Set();
 78        }
    
 79        #endregion
 
 80
 81
 82        处理异常#region 处理异常
 83        /**//// <summary>
 84        /// 改变异常信号量
 85        /// </summary>
 86        /// <param name="hasException"></param>

 87        private void ChangeExceptionStatus(bool hasException)
 88        {
 89            lock(this)
 90            {
 91                this.hasException = hasException;
 92            }

 93        }

 94        /**//// <summary>
 95        /// 生成异常类
 96        /// </summary>
 97        /// <param name="msg"></param>

 98        private void UpdateExceptionMessage(string msg)
 99        {        
100            socketException = new Exception(msg);
101        }

102        /**//// <summary>
103        /// 判断是否产生了异常
104        /// </summary>

105        private void HasException()
106        {
107            lock(this)
108            {
109                if(hasException == true)
110                {
111                    throw socketException;
112                }

113            }

114        }

115        #endregion

116
117
118        业务#region 业务
119        /**//// <summary>
120        /// 作一次业务请求
121        /// </summary>
122        /// <param name="package"></param>

123        protected void BusinessRequet(byte[] package)
124        {            
125            MobileClient mobileClient = this.GetMobileClient();        
126            mobileClient.Connect();    
127            this.connectDone.WaitOne();
128            HasException();
129
130            mobileClient.Send(package);
131            this.sendDone.WaitOne();
132            HasException();
133
134            mobileClient.Receive();
135            this.receiveDone.WaitOne();
136            HasException();
137
138            receicedBytes = Encoding.ASCII.GetBytes( mobileClient.ReceivedData);
139            mobileClient.Close();
140            
141        }

142}
posted @ 2009-11-02 11:56  vhtt  阅读(558)  评论(0)    收藏  举报