转自听香水榭] 一个封装的异步Socket客户端
一个封装的异步Socket客户端
业务类在对此包装的socket进行访问时,由于是三个线程之间进行通讯,这个线程无法捕捉另一个线程产生的异常,所以通过信号量来通知是否有异常的产生:
1
using System;
2
using System.Collections;
3
using System.Configuration;
4
using System.Net;
5
using System.Net.Sockets;
6
using System.Text;
7
8
namespace 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
if( this.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
if( this.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
if( this.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
using System;2
using System.Collections;3
using System.Configuration;4
using System.Net;5
using System.Net.Sockets;6
using System.Text;7

8
namespace Beijing.Traffic.Mobile.Net9
{10
/**//// <summary>11
/// 智能手机端网络访问类12
/// </summary>13
public class MobileClient14
{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
else78
{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
try93
{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
try117
{ 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
else130
{ 131
//连接失败事件 132
this.HandlerException("连接远程服务器失败");133
134
}135
}136
catch(Exception ex)137
{138
this.Close();139
this.HandlerException(ex.Message);140
}141
} 142
#endregion143

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
try156
{157
if( this.socket == null || !this.socket.Connected )158
{159
throw new Exception("远程服务器没有连接,请先连接");160
}161
else162
{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
if( this.OnSendFinished != null)186
{ 187
UpdateEventMessage("发送数据成功");188
OnSendFinished(this,socketEventArgs);189
}190
}191
else192
{ 193
this.HandlerException("发送数据失败"); 194
}195
196
} 197
catch (Exception ex) 198
{199
this.Close();200
this.HandlerException(ex.Message);201
}202
}203

204

205
#endregion206

207
异步接受数据#region 异步接受数据208

209
public void Receive()210
{211
try212
{213
if( this.socket == null || !this.socket.Connected )214
{215
throw new Exception("远程服务器没有连接,请先连接");216
}217
else218
{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
try235
{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
else245
{ 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
else257
{ 258
this.HandlerException("接受数据为空"); 259
}260
}261
}262
catch( Exception ex )263
{264
this.Close();265
this.HandlerException(ex.Message);266
}267
}268

269

270
#endregion271

272
接收到的数据#region 接收到的数据273
/**//// <summary>274
/// 接收到的数据275
/// </summary>276
public string ReceivedData277
{278
get279
{280
lock(this)281
{282
return this.receiveData.ToString();283
}284
}285
}286

287
#endregion288

289
关闭socket#region 关闭socket290

291
public void Close()292
{293
try294
{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
#endregion309

310

311
}312
}313

业务类在对此包装的socket进行访问时,由于是三个线程之间进行通讯,这个线程无法捕捉另一个线程产生的异常,所以通过信号量来通知是否有异常的产生:
1
#define TEST
2
3
using System;
4
using System.Threading;
5
using System.Text;
6
using Beijing.Traffic.Mobile.Net;
7
8
namespace 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
}
#define TEST2

3
using System;4
using System.Threading;5
using System.Text;6
using Beijing.Traffic.Mobile.Net;7

8
namespace Beijing.Traffic.Mobile.Bussiness9
{10

11
/**//// <summary>12
/// 业务逻辑的基类。13
/// </summary>14
public abstract class BussinessBase15
{16
#if TEST17
//手机Socket客户端18
public MobileClient mobileClient = null;19
20
#else21
protected MobileClient mobileClient = null;22
#endif23
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
#endregion116

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
}