您的位置:首页 > Web前端

对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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息