项目需要封装一个异步Socket客户端,现将代码写下来,请各位指点一下 :
业务类在对此包装的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
{
if( this.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)
{
if( this.OnSendFinished != null)
{
UpdateEventMessage("发送数据成功");
OnSendFinished(this,socketEventArgs);
}
}
else
{
this.HandlerException("发送数据失败");
}
}
catch (Exception ex)
{
this.Close();
this.HandlerException(ex.Message);
}
}
#endregion
#region 异步接受数据
public void Receive()
{
try
{
if( this.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
}
}
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
{
if( this.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)
{
if( this.OnSendFinished != null)
{
UpdateEventMessage("发送数据成功");
OnSendFinished(this,socketEventArgs);
}
}
else
{
this.HandlerException("发送数据失败");
}
}
catch (Exception ex)
{
this.Close();
this.HandlerException(ex.Message);
}
}
#endregion
#region 异步接受数据
public void Receive()
{
try
{
if( this.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();
}
}
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();
}
}