听香水榭

半壁草房待明月,一盏清茗酬知音
  首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一个封装的异步Socket客户端

Posted on 2005-09-09 17:09  清雷  阅读(2462)  评论(2编辑  收藏  举报
   项目需要封装一个异步Socket客户端,现将代码写下来,请各位指点一下 :
using System;
using System.Collections;
using System.Configuration;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Beijing.Traffic.Mobile.Net
{
    
/// <summary>
    
/// 智能手机端网络访问类
    
/// </summary>

    public class MobileClient
    
{
        
//服务器IP地址
        private string serverIP;
        
//服务器访问端口
        private string serverPort;
        
private Socket socket;
        
private byte [] buffer = new byte[256];
        
private StringBuilder receiveData = null;
        
private SocketEventArgs socketEventArgs = null

        
#region 事件
        
//连接完成事件
        public event EventHandler OnConnect;        
        
//接收完成事件 
        public event EventHandler OnReceivedFinshed;        
        
//发送数据成功
        public event EventHandler OnSendFinished;        
        
//产生异常时调用此事件
        public event EventHandler OnException;

        
#endregion
          

        
#region 构造函数

        
public MobileClient()
        
{    
            
this.serverIP = ConfigurationSettings.AppSettings["ServerIP"];
            
this.serverPort = ConfigurationSettings.AppSettings["ServerPort"];
            receiveData 
= new StringBuilder();            
        }

        
public MobileClient(string ip,string port)
        
{
            
this.serverIP = ip;
            
this.serverPort = port;
            receiveData 
= new StringBuilder();
            
        }
        
        
#endregion
    

        
private void UpdateEventMessage(string msg)
        
{
            
if( socketEventArgs == null)
            
{
                socketEventArgs 
= new SocketEventArgs();
                socketEventArgs.ServerIP 
= this.serverIP;
                socketEventArgs.ServerPort 
= this.serverPort;
            }

            socketEventArgs.Message 
= msg;

        }


        
/// <summary>
        
/// 处理异常的事件
        
/// </summary>
        
/// <param name="msg"></param>

        private void  HandlerException(string msg)
        
{
            
if(OnException != null)
            
{
                UpdateEventMessage(msg);                
                OnException(
this,socketEventArgs);

            }

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

        }


        
#region 连接远程服务器


        
/// <summary>
        
/// 异步连接远程服务器
        
/// </summary>
        
/// <returns></returns>

        public void Connect()
        
{
            
try
            
{
                
if( socket != null && socket.Connected )
                
{
                    socket.Shutdown( SocketShutdown.Both );
                    System.Threading.Thread.Sleep( 
10 );
                    socket.Close();
                }

                socket 
= new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );    

                IPEndPoint epServer 
= new IPEndPoint(IPAddress.Parse(serverIP),int.Parse(serverPort));
                
                socket.Blocking 
= false;                        
                socket.BeginConnect( epServer, 
new AsyncCallback(Connected),socket );
            }

            
catch(Exception ex)
            
{
                
this.Close();
                
this.HandlerException(ex.Message);
            }

        }


        
private void Connected( IAsyncResult ar )
        
{
            
try
            
{                
                Socket sock 
= (Socket)ar.AsyncState;            
                            
                
if( sock.Connected )
                
{
                    
if(OnConnect != null)
                    
{
                        
//连接成功事件                        
                        UpdateEventMessage("连接远程服务器成功");
                        OnConnect(
this,socketEventArgs);
                    }

                }

                
else
                
{                    
                    
//连接失败事件                            
                    this.HandlerException("连接远程服务器失败");
                    
                }

            }

            
catch(Exception ex)
            
{
                
this.Close();
                
this.HandlerException(ex.Message);
            }

        }
        
        
#endregion


        
#region 异步发送数据

        
public void Send(string msg)
        
{        
            
byte[] msgBytes = Encoding.ASCII.GetBytes(msg);
            Send(msgBytes);

        }


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

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

            }

            
catch(Exception ex)
            
{
                
this.Close();
                
this.HandlerException(ex.Message);
            }


        }



        
private  void SendCallback(IAsyncResult ar) 
        
{
            
try 
            
{                
                Socket client 
= (Socket) ar.AsyncState;                
                
int bytesSent = client.EndSend(ar);

                
if( bytesSent > 0)
                
{
                    
ifthis.OnSendFinished != null)
                    
{                        
                        UpdateEventMessage(
"发送数据成功");
                        OnSendFinished(
this,socketEventArgs);
                    }

                }

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

                
            }
 
            
catch (Exception ex) 
            
{
                
this.Close();
                
this.HandlerException(ex.Message);
            }

        }



        
#endregion


        
#region 异步接受数据

        
public void Receive()
        
{
            
try
            
{
                
ifthis.socket == null || !this.socket.Connected )
                
{
                    
throw new Exception("远程服务器没有连接,请先连接");
                }

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

            }

            
catch( Exception ex )
            
{
                
this.Close();
                
this.HandlerException(ex.Message);
            }

        }



        
private void OnReceiveData(IAsyncResult ar)
        
{
            Socket sock 
= (Socket)ar.AsyncState;
            
try
            
{
                
int nBytesRec = sock.EndReceive( ar );
                
if( nBytesRec > 0 )
                
{
                    
//接受数据并保存
                    string sRecieved = Encoding.ASCII.GetString(buffer, 0, nBytesRec );
                    receiveData.Append(sRecieved);
                    Receive();
                }

                
else
                
{                    
                    sock.Shutdown( SocketShutdown.Both );
                    sock.Close();
                    
if(receiveData.Length != 0)
                    
{
                        
if(OnReceivedFinshed != null)
                        
{                        
                            UpdateEventMessage(
"接受数据成功");
                            OnReceivedFinshed(
this,socketEventArgs);
                        }

                    }

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

                }

            }

            
catch( Exception ex )
            
{
                
this.Close();
                
this.HandlerException(ex.Message);
            }

        }



        
#endregion


        
#region 接收到的数据
        
/// <summary>
        
/// 接收到的数据
        
/// </summary>

        public string ReceivedData
        
{
            
get
            
{
                
lock(this)
                
{
                    
return this.receiveData.ToString();
                }

            }

        }


        
#endregion


        
#region 关闭socket

        
public void Close()
        
{
            
try
            
{
                
if( socket != null && socket.Connected )
                
{
                    socket.Shutdown( SocketShutdown.Both );
                    System.Threading.Thread.Sleep( 
10 );
                    socket.Close();
                }

            }

            
catch(Exception ex)
            
{
                
this.HandlerException(ex.Message);
            }

        }


        
#endregion



    }

}


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

using System;
using System.Threading;
using System.Text;
using Beijing.Traffic.Mobile.Net;

namespace Beijing.Traffic.Mobile.Bussiness
{

    
/// <summary>
    
/// 业务逻辑的基类。
    
/// </summary>

    public abstract class BussinessBase
    
{
#if TEST
        
//手机Socket客户端
        public MobileClient mobileClient = null;
        
#else
        
protected MobileClient mobileClient = null;
#endif
        
        
protected byte[] receicedBytes = null;
        
//是否产生了Socket异常
        private bool hasException = false;
        
//异常消息类
        private Exception socketException = null;
        
        
//三个线程通知事件
        protected ManualResetEvent connectDone = new ManualResetEvent(false);
        
protected ManualResetEvent sendDone = new ManualResetEvent(false);
        
protected ManualResetEvent receiveDone = new ManualResetEvent(false);    

        
public BussinessBase()
        
{            
        }

        
/// <summary>
        
/// 获取手机网络连接客户端类
        
/// </summary>
        
/// <returns></returns>

        public MobileClient GetMobileClient()
        
{
            
            
if(mobileClient == null)
            
{
                mobileClient 
= new MobileClient("210.73.74.200","3333");
                mobileClient.OnConnect 
+= new EventHandler(mobileClient_OnConnect);                
                mobileClient.OnSendFinished 
+=new EventHandler(mobileClient_OnSendFinished);
                mobileClient.OnReceivedFinshed 
+=new EventHandler(mobileClient_OnReceivedFinshed);
                mobileClient.OnException 
+= new EventHandler(mobileClient_OnException);
            }

            
return mobileClient;
        }



        
#region 事件
        
protected void mobileClient_OnConnect(object sender, System.EventArgs e)
        
{
            
this.connectDone.Set();
        }

        
protected void mobileClient_OnException(object sender, System.EventArgs e)
        
{
            SocketEventArgs socketEventArgs 
= e as SocketEventArgs;
            ChangeExceptionStatus(
true);
            UpdateExceptionMessage(socketEventArgs.Message);
            
this.connectDone.Set();            
        }

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

        
protected void mobileClient_OnReceivedFinshed(object sender, System.EventArgs e)
        
{
            ChangeExceptionStatus(
false);
            
this.receiveDone.Set();
        }
    
        
#endregion
 


        
#region 处理异常
        
/// <summary>
        
/// 改变异常信号量
        
/// </summary>
        
/// <param name="hasException"></param>

        private void ChangeExceptionStatus(bool hasException)
        
{
            
lock(this)
            
{
                
this.hasException = hasException;
            }

        }

        
/// <summary>
        
/// 生成异常类
        
/// </summary>
        
/// <param name="msg"></param>

        private void UpdateExceptionMessage(string msg)
        
{        
            socketException 
= new Exception(msg);
        }

        
/// <summary>
        
/// 判断是否产生了异常
        
/// </summary>

        private void HasException()
        
{
            
lock(this)
            
{
                
if(hasException == true)
                
{
                    
throw socketException;
                }

            }

        }

        
#endregion



        
#region 业务
        
/// <summary>
        
/// 作一次业务请求
        
/// </summary>
        
/// <param name="package"></param>

        protected void BusinessRequet(byte[] package)
        
{            
            MobileClient mobileClient 
= this.GetMobileClient();        
            mobileClient.Connect();    
            
this.connectDone.WaitOne();
            HasException();

            mobileClient.Send(package);
            
this.sendDone.WaitOne();
            HasException();

            mobileClient.Receive();
            
this.receiveDone.WaitOne();
            HasException();

            receicedBytes 
= Encoding.ASCII.GetBytes( mobileClient.ReceivedData);
            mobileClient.Close();
            
        }

}