对Socket常用方法的封装
2007-08-25 05:53
351 查看
在一个blog上看到的好帖,写了一个对网络 socket 进行封装的类,主要是在异步阻塞模式下进行数据、文件的发送的发送和接收,都是静态方法。代码如下:
1
using System;
2
using System.Net ;
3
using System.Net.Sockets ;
4
using System.IO ;
5
using LogDll;
6
7
namespace NetDll
8
{
9
// <summary>
10
/// Net : 提供静态方法,对常用的网络操作进行封装
11
/// </summary>
12
public sealed class Net
13
{
14
private Net(){
15
}
16
17
/**//// <summary>
18
/// 连接使用 tcp 协议的服务端
19
/// </summary>
20
/// <param name="ip">服务端的ip地址</param>
21
/// <param name="port">服务端的端口号</param>
22
/// <returns></returns>
23
public static Socket ConnectServer( string ip ,int port ) {
24
Socket s = null;
25
26
try {
27
IPAddress ipAddress = IPAddress.Parse ( ip );
28
IPEndPoint ipEndPoint = new IPEndPoint ( ipAddress,port );
29
s = new Socket ( ipEndPoint.AddressFamily ,SocketType.Stream ,ProtocolType.Tcp );
30
s.Connect ( ipEndPoint );
31
if ( s.Connected== false ) {
32
s = null;
33
}
34
}
35
catch ( Exception e ) {
36
Log.WriteLog ( e );
37
}
38
return s;
39
}
40
41
/**//// <summary>
42
/// 用主机名称连接使用Tcp协议的服务端
43
/// </summary>
44
/// <param name="hostName">在hosts 文件中存在的主机名称</param>
45
/// <param name="port">服务端的端口号</param>
46
/// <returns></returns>
47
public static Socket ConnectServByHostName( string hostName,int port ){
48
Socket s = null;
49
IPHostEntry iphe = null;
50
51
try {
52
iphe = Dns.Resolve ( hostName );
53
foreach ( IPAddress ipad in iphe.AddressList ) {
54
IPEndPoint ipe = new IPEndPoint (ipad,port);
55
Socket tmps = new Socket (ipe.AddressFamily ,SocketType.Stream ,ProtocolType.Tcp );
56
tmps.Connect ( ipe );
57
58
if ( tmps.Connected ) {
59
s = tmps;
60
break;
61
}
62
else
63
continue;
64
}
65
}
66
catch ( Exception e ) {
67
Log.WriteLog ( e );
68
}
69
return s;
70
}
71
72
/**//// <summary>
73
/// 向远程主机发送数据
74
/// </summary>
75
/// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>
76
/// <param name="buffer">待发送的数据</param>
77
/// <param name="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
78
/// <returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
79
/// <remarks >
80
/// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
81
/// </remarks>
82
public static int SendData ( Socket socket,byte[] buffer,int outTime ) {
83
if ( socket == null ||socket.Connected == false ) {
84
throw new ArgumentException ("参数socket 为null,或者未连接到远程计算机");
85
}
86
if ( buffer == null || buffer.Length == 0 ) {
87
throw new ArgumentException ("参数buffer 为null ,或者长度为 0");
88
}
89
90
int flag = 0;
91
try {
92
int left = buffer.Length ;
93
int sndLen = 0;
94
95
while ( true ) {
96
if ( ( socket.Poll (outTime*1000000,SelectMode.SelectWrite ) == true ) ) { // 收集了足够多的传出数据后开始发送
97
sndLen = socket.Send (buffer,sndLen ,left ,SocketFlags.None );
98
left -= sndLen ;
99
if ( left == 0 ) // 数据已经全部发送
100
flag = 0;
101
break;
102
}
103
else {
104
if ( sndLen > 0 ) { // 数据部分已经被发送
105
continue;
106
}
107
else { // 发送数据发生错误
108
flag = -2;
109
break;
110
}
111
}
112
}
113
else { // 超时退出
114
flag = -1;
115
break;
116
}
117
}
118
}
119
catch ( SocketException e ) {
120
Log.WriteLog ( e );
121
flag = -3;
122
}
123
return flag;
124
}
125
126
127
/**//// <summary>
128
/// 向远程主机发送数据
129
/// </summary>
130
/// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>
131
/// <param name="buffer">待发送的字符串</param>
132
/// <param name="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
133
/// <returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
134
/// <remarks >
135
/// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
136
/// </remarks>
137
public static int SendData ( Socket socket,string buffer,int outTime ) {
138
if ( buffer == null || buffer.Length == 0 ) {
139
throw new ArgumentException ("待发送的字符串长度不能为零.");
140
}
141
return ( SendData ( socket,System.Text .Encoding .Default .GetBytes ( buffer ),outTime) );
142
}
143
144
145
/**//// <summary>
146
/// 接收远程主机发送的数据
147
/// </summary>
148
/// <param name="socket">要接收数据且已经连接到远程主机的 socket</param>
149
/// <param name="buffer">接收数据的缓冲区</param>
150
/// <param name="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>
151
/// <returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>
152
/// <remarks >
153
/// 1、当 outTime 指定为-1时,将一直等待直到有数据需要接收;
154
/// 2、需要接收的数据的长度,由 buffer 的长度决定。
155
/// </remarks>
156
public static int RecvData ( Socket socket,byte[] buffer ,int outTime ) {
157
if ( socket == null || socket.Connected == false ) {
158
throw new ArgumentException ("参数socket 为null,或者未连接到远程计算机");
159
}
160
if ( buffer == null || buffer.Length == 0 ) {
161
throw new ArgumentException ("参数buffer 为null ,或者长度为 0");
162
}
163
buffer.Initialize ();
164
int left = buffer.Length ;
165
int curRcv = 0;
166
int flag = 0;
167
168
try {
169
while ( true ) {
170
if ( socket.Poll (outTime*1000000,SelectMode.SelectRead ) == true ) { // 已经有数据等待接收
171
curRcv = socket.Receive (buffer,curRcv,left ,SocketFlags.None );
172
left -= curRcv;
173
if ( left == 0 ) { // 数据已经全部接收
174
flag = 0;
175
break;
176
}
177
else {
178
if ( curRcv > 0 ) { // 数据已经部分接收
179
continue;
180
}
181
else { // 出现错误
182
flag = -2;
183
break;
184
}
185
}
186
}
187
else { // 超时退出
188
flag = -1;
189
break;
190
}
191
}
192
}
193
catch ( SocketException e ) {
194
Log.WriteLog ( e );
195
flag = -3;
196
}
197
return flag;
198
}
199
200
/**//// <summary>
201
/// 接收远程主机发送的数据
202
/// </summary>
203
/// <param name="socket">要接收数据且已经连接到远程主机的 socket</param>
204
/// <param name="buffer">存储接收到的数据的字符串</param>
205
/// <param name="bufferLen">待接收的数据的长度</param>
206
/// <param name="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>
207
/// <returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>
208
/// <remarks >
209
/// 当 outTime 指定为-1时,将一直等待直到有数据需要接收;
210
/// </remarks>
211
public static int RecvData ( Socket socket,string buffer ,int bufferLen,int outTime ) {
212
if ( bufferLen <= 0 ) {
213
throw new ArgumentException ("存储待接收数据的缓冲区长度必须大于0");
214
}
215
byte[] tmp = new byte [ bufferLen ];
216
int flag = 0;
217
if ( ( flag = RecvData ( socket,tmp,outTime)) == 0) {
218
buffer = System.Text.Encoding .Default .GetString ( tmp );
219
}
220
return flag;
221
}
222
223
224
/**//// <summary>
225
/// 向远程主机发送文件
226
/// </summary>
227
/// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>
228
/// <param name="fileName">待发送的文件名称</param>
229
/// <param name="maxBufferLength">文件发送时的缓冲区大小</param>
230
/// <param name="outTime">发送缓冲区中的数据的超时时间</param>
231
/// <returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>
232
/// <remarks >
233
/// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
234
/// </remarks>
235
public static int SendFile ( Socket socket ,string fileName,int maxBufferLength,int outTime ) {
236
if ( fileName == null || maxBufferLength <= 0 ) {
237
throw new ArgumentException ("待发送的文件名称为空或发送缓冲区的大小设置不正确.");
238
}
239
240
int flag = 0;
241
try {
242
FileStream fs = new FileStream ( fileName,FileMode.Open ,FileAccess.Read );
243
long fileLen = fs.Length ; // 文件长度
244
long leftLen = fileLen; // 未读取部分
245
int readLen = 0; // 已读取部分
246
byte[] buffer = null;
247
248
if ( fileLen <= maxBufferLength ) { /**//* 文件可以一次读取*/
249
buffer = new byte [ fileLen ];
250
readLen = fs.Read (buffer,0,(int )fileLen );
251
flag = SendData( socket,buffer,outTime );
252
}
253
else { /**//* 循环读取文件,并发送 */
254
buffer = new byte[ maxBufferLength ];
255
while ( leftLen != 0 ) {
256
readLen = fs.Read (buffer,0,maxBufferLength );
257
if ( (flag = SendData( socket,buffer,outTime ) ) < 0 ) {
258
break;
259
}
260
leftLen -= readLen;
261
}
262
}
263
fs.Close ();
264
}
265
catch ( IOException e ) {
266
Log.WriteLog ( e );
267
flag = -4;
268
}
269
return flag;
270
}
271
272
/**//// <summary>
273
/// 向远程主机发送文件
274
/// </summary>
275
/// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>
276
/// <param name="fileName">待发送的文件名称</param>
277
/// <returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>
278
public static int SendFile ( Socket socket ,string fileName ) {
279
return SendFile ( socket,fileName,2048,1 );
280
}
281
282
283
/**//// <summary>
284
/// 接收远程主机发送的文件
285
/// </summary>
286
/// <param name="socket">待接收数据且已经连接到远程主机的 socket</param>
287
/// <param name="fileName">保存接收到的数据的文件名</param>
288
/// <param name="fileLength" >待接收的文件的长度</param>
289
/// <param name="maxBufferLength">接收文件时最大的缓冲区大小</param>
290
/// <param name="outTime">接受缓冲区数据的超时时间</param>
291
/// <returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>
292
/// <remarks >
293
/// 当 outTime 指定为-1时,将一直等待直到有数据需要接收
294
/// </remarks>
295
public static int RecvFile ( Socket socket ,string fileName,long fileLength,int maxBufferLength,int outTime ) {
296
if ( fileName == null || maxBufferLength <= 0 ) {
297
throw new ArgumentException ("保存接收数据的文件名称为空或发送缓冲区的大小设置不正确.");
298
}
299
300
int flag = 0;
301
try {
302
FileStream fs = new FileStream (fileName,FileMode.Create);
303
byte [] buffer = null;
304
305
if ( fileLength <= maxBufferLength ) { /**//* 一次读取所传送的文件 */
306
buffer = new byte [ fileLength ];
307
if ( ( flag =RecvData(socket,buffer,outTime ) ) == 0 ) {
308
fs.Write ( buffer,0,(int)fileLength);
309
}
310
}
311
else { /**//* 循环读取网络数据,并写入文件 */
312
int rcvLen = maxBufferLength;
313
long leftLen = fileLength; //剩下未写入的数据
314
buffer = new byte [ rcvLen ];
315
316
while ( leftLen != 0 ) {
317
if ( ( flag =RecvData(socket,buffer,outTime ) ) < 0 ) {
318
break;
319
}
320
fs.Write (buffer,0,rcvLen );
321
leftLen -= rcvLen;
322
rcvLen = ( maxBufferLength < leftLen ) ? maxBufferLength :((int) leftLen) ;
323
}
324
}
325
fs.Close ();
326
}
327
catch ( IOException e ) {
328
Log.WriteLog ( e );
329
flag = -4;
330
}
331
return flag;
332
}
333
334
/**//// <summary>
335
/// 接收远程主机发送的文件
336
/// </summary>
337
/// <param name="socket">待接收数据且已经连接到远程主机的 socket</param>
338
/// <param name="fileName">保存接收到的数据的文件名</param>
339
/// <param name="fileLength" >待接收的文件的长度</param>
340
/// <returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>
341
public static int RecvFile ( Socket socket,string fileName,long fileLength ) {
342
return RecvFile ( socket,fileName,fileLength,2048,1);
343
}
344
}
345
}
346
在这个类中用到了一个 LogDll 的组件,主要完成发生异常或错误的时候,将信息输出到日志文件。用到了“winform 程序的配置文件——App.config ”中提到的内容,代码如下:
1
#define DEBUG
2
3
using System;
4
using System.Diagnostics ;
5
6
namespace LogDll
7
{
8
/**//// <summary>
9
/// Log : 将系统运行信息写入到日志文件
10
/// </summary>
11
/// <remarks >需要在项目的配置文件中增加如下的信息:
12
/// <configuration>
13
/// <system.diagnostics>
14
/// <switches>
15
/// <add name="MagicTraceSwitch" value="3" />
16
/// </switches>
17
/// <trace autoflush="true" indentsize="4">
18
/// <listeners>
19
/// <add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="myListener.log" />
20
/// <remove type="System.Diagnostics.DefaultTraceListener" />
21
/// </listeners>
22
/// </trace>
23
/// </system.diagnostics>
24
/// </configuration>
25
/// 其中的initializeData="myListener.log",替换为自己的日志文件名称
26
/// </remarks>
27
public class Log
28
{
29
private Log(){
30
}
31
32
public static void WriteLog ( Exception e ) {
33
Debug.WriteLine ( DateTime.Now .ToString () + ": " + e.Message +" ["+e.StackTrace +"]");
34
}
35
36
public static void WriteLog ( string message,string sourceFile ) {
37
Debug.WriteLine ( DateTime.Now .ToString () + ": " + message + " ["+sourceFile +"]");
38
}
39
40
public static void WriteLog ( string message ) {
41
Debug.WriteLine ( DateTime.Now .ToString () + ": " + message );
42
}
43
}
44
}
45
相关文章推荐
- Socket一些常用的方法封装
- 对Socket常用方法的封装
- JQuery 封装 Ajax 常用方法(推荐)
- java操作hdfs常用方法封装
- JS中常用方法的封装【转载】
- Sqlite3 数据库介绍及常用方法的简单封装
- 在Unity中常用到的一些安卓方法封装
- C# HTTP网络常用方法封装
- jquery封装常用方法
- js 常用封装方法
- C#中常用的字符串加密,解密方法封装
- DOM库及常用方法封装
- JS中常用方法的封装【转载】
- ASP.NET常用方法函数汇总封装文件
- C#中常用的字符串加密,解密方法封装,包含只加密,不解密的方法
- Socket网络编程学习笔记(1):常用方法介绍
- Android BaseActivity、BaseFragment等 常用方法封装
- IOS 常用方法封装
- android常用方法封装(一)
- 常用ajax封装的方法