对Socket常用方法的封装

在一个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>

12publicsealedclassNet
13{
14privateNet(){
15}

16
17/**////<summary>
18///连接使用tcp协议的服务端
19///</summary>
20///<paramname="ip">服务端的ip地址</param>
21///<paramname="port">服务端的端口号</param>
22///<returns></returns>

23publicstaticSocketConnectServer(stringip,intport){
24Sockets=null;
25
26try{
27IPAddressipAddress=IPAddress.Parse(ip);
28IPEndPointipEndPoint=newIPEndPoint(ipAddress,port);
29s=newSocket(ipEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
30s.Connect(ipEndPoint);
31if(s.Connected==false){
32s=null;
33}

34}

35catch(Exceptione){
36Log.WriteLog(e);
37}

38returns;
39}

40
41/**////<summary>
42///用主机名称连接使用Tcp协议的服务端
43///</summary>
44///<paramname="hostName">在hosts文件中存在的主机名称</param>
45///<paramname="port">服务端的端口号</param>
46///<returns></returns>

47publicstaticSocketConnectServByHostName(stringhostName,intport){
48Sockets=null;
49IPHostEntryiphe=null;
50
51try{
52iphe=Dns.Resolve(hostName);
53foreach(IPAddressipadiniphe.AddressList){
54IPEndPointipe=newIPEndPoint(ipad,port);
55Sockettmps=newSocket(ipe.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
56tmps.Connect(ipe);
57
58if(tmps.Connected){
59s=tmps;
60break;
61}

62else
63continue;
64}

65}

66catch(Exceptione){
67Log.WriteLog(e);
68}

69returns;
70}

71
72/**////<summary>
73///向远程主机发送数据
74///</summary>
75///<paramname="socket">要发送数据且已经连接到远程主机的Socket</param>
76///<paramname="buffer">待发送的数据</param>
77///<paramname="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
78///<returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
79///<remarks>
80///当outTime指定为-1时,将一直等待直到有数据需要发送
81///</remarks>

82publicstaticintSendData(Socketsocket,byte[]buffer,intoutTime){
83if(socket==null||socket.Connected==false){
84thrownewArgumentException("参数socket为null,或者未连接到远程计算机");
85}

86if(buffer==null||buffer.Length==0){
87thrownewArgumentException("参数buffer为null,或者长度为0");
88}

89
90intflag=0;
91try{
92intleft=buffer.Length;
93intsndLen=0;
94
95while(true){
96if((socket.Poll(outTime*1000000,SelectMode.SelectWrite)==true)){//收集了足够多的传出数据后开始发送
97sndLen=socket.Send(buffer,sndLen,left,SocketFlags.None);
98left-=sndLen;
99if(left==0)//数据已经全部发送
100flag=0;
101break;
102}

103else{
104if(sndLen>0){//数据部分已经被发送
105continue;
106}

107else{//发送数据发生错误
108flag=-2;
109break;
110}

111}

112}

113else{//超时退出
114flag=-1;
115break;
116}

117}

118}

119catch(SocketExceptione){
120Log.WriteLog(e);
121flag=-3;
122}

123returnflag;
124}

125
126
127/**////<summary>
128///向远程主机发送数据
129///</summary>
130///<paramname="socket">要发送数据且已经连接到远程主机的Socket</param>
131///<paramname="buffer">待发送的字符串</param>
132///<paramname="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
133///<returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
134///<remarks>
135///当outTime指定为-1时,将一直等待直到有数据需要发送
136///</remarks>

137publicstaticintSendData(Socketsocket,stringbuffer,intoutTime){
138if(buffer==null||buffer.Length==0){
139thrownewArgumentException("待发送的字符串长度不能为零.");
140}

141return(SendData(socket,System.Text.Encoding.Default.GetBytes(buffer),outTime));
142}

143
144
145/**////<summary>
146///接收远程主机发送的数据
147///</summary>
148///<paramname="socket">要接收数据且已经连接到远程主机的socket</param>
149///<paramname="buffer">接收数据的缓冲区</param>
150///<paramname="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>
151///<returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>
152///<remarks>
153///1、当outTime指定为-1时,将一直等待直到有数据需要接收;
154///2、需要接收的数据的长度,由buffer的长度决定。
155///</remarks>

156publicstaticintRecvData(Socketsocket,byte[]buffer,intoutTime){
157if(socket==null||socket.Connected==false){
158thrownewArgumentException("参数socket为null,或者未连接到远程计算机");
159}

160if(buffer==null||buffer.Length==0){
161thrownewArgumentException("参数buffer为null,或者长度为0");
162}

163buffer.Initialize();
164intleft=buffer.Length;
165intcurRcv=0;
166intflag=0;
167
168try{
169while(true){
170if(socket.Poll(outTime*1000000,SelectMode.SelectRead)==true){//已经有数据等待接收
171curRcv=socket.Receive(buffer,curRcv,left,SocketFlags.None);
172left-=curRcv;
173if(left==0){//数据已经全部接收
174flag=0;
175break;
176}

177else{
178if(curRcv>0){//数据已经部分接收
179continue;
180}

181else{//出现错误
182flag=-2;
183break;
184}

185}

186}

187else{//超时退出
188flag=-1;
189break;
190}

191}

192}

193catch(SocketExceptione){
194Log.WriteLog(e);
195flag=-3;
196}

197returnflag;
198}

199
200/**////<summary>
201///接收远程主机发送的数据
202///</summary>
203///<paramname="socket">要接收数据且已经连接到远程主机的socket</param>
204///<paramname="buffer">存储接收到的数据的字符串</param>
205///<paramname="bufferLen">待接收的数据的长度</param>
206///<paramname="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>
207///<returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>
208///<remarks>
209///当outTime指定为-1时,将一直等待直到有数据需要接收;
210///</remarks>

211publicstaticintRecvData(Socketsocket,stringbuffer,intbufferLen,intoutTime){
212if(bufferLen<=0){
213thrownewArgumentException("存储待接收数据的缓冲区长度必须大于0");
214}

215byte[]tmp=newbyte[bufferLen];
216intflag=0;
217if((flag=RecvData(socket,tmp,outTime))==0){
218buffer=System.Text.Encoding.Default.GetString(tmp);
219}

220returnflag;
221}

222
223
224/**////<summary>
225///向远程主机发送文件
226///</summary>
227///<paramname="socket">要发送数据且已经连接到远程主机的socket</param>
228///<paramname="fileName">待发送的文件名称</param>
229///<paramname="maxBufferLength">文件发送时的缓冲区大小</param>
230///<paramname="outTime">发送缓冲区中的数据的超时时间</param>
231///<returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>
232///<remarks>
233///当outTime指定为-1时,将一直等待直到有数据需要发送
234///</remarks>

235publicstaticintSendFile(Socketsocket,stringfileName,intmaxBufferLength,intoutTime){
236if(fileName==null||maxBufferLength<=0){
237thrownewArgumentException("待发送的文件名称为空或发送缓冲区的大小设置不正确.");
238}

239
240intflag=0;
241try{
242FileStreamfs=newFileStream(fileName,FileMode.Open,FileAccess.Read);
243longfileLen=fs.Length;//文件长度
244longleftLen=fileLen;//未读取部分
245intreadLen=0;//已读取部分
246byte[]buffer=null;
247
248if(fileLen<=maxBufferLength){/**//*文件可以一次读取*/
249buffer=newbyte[fileLen];
250readLen=fs.Read(buffer,0,(int)fileLen);
251flag=SendData(socket,buffer,outTime);
252}

253else{/**//*循环读取文件,并发送*/
254buffer=newbyte[maxBufferLength];
255while(leftLen!=0){
256readLen=fs.Read(buffer,0,maxBufferLength);
257if((flag=SendData(socket,buffer,outTime))<0){
258break;
259}

260leftLen-=readLen;
261}

262}

263fs.Close();
264}

265catch(IOExceptione){
266Log.WriteLog(e);
267flag=-4;
268}

269returnflag;
270}

271
272/**////<summary>
273///向远程主机发送文件
274///</summary>
275///<paramname="socket">要发送数据且已经连接到远程主机的socket</param>
276///<paramname="fileName">待发送的文件名称</param>
277///<returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>

278publicstaticintSendFile(Socketsocket,stringfileName){
279returnSendFile(socket,fileName,2048,1);
280}

281
282
283/**////<summary>
284///接收远程主机发送的文件
285///</summary>
286///<paramname="socket">待接收数据且已经连接到远程主机的socket</param>
287///<paramname="fileName">保存接收到的数据的文件名</param>
288///<paramname="fileLength">待接收的文件的长度</param>
289///<paramname="maxBufferLength">接收文件时最大的缓冲区大小</param>
290///<paramname="outTime">接受缓冲区数据的超时时间</param>
291///<returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>
292///<remarks>
293///当outTime指定为-1时,将一直等待直到有数据需要接收
294///</remarks>

295publicstaticintRecvFile(Socketsocket,stringfileName,longfileLength,intmaxBufferLength,intoutTime){
296if(fileName==null||maxBufferLength<=0){
297thrownewArgumentException("保存接收数据的文件名称为空或发送缓冲区的大小设置不正确.");
298}

299
300intflag=0;
301try{
302FileStreamfs=newFileStream(fileName,FileMode.Create);
303byte[]buffer=null;
304
305if(fileLength<=maxBufferLength){/**//*一次读取所传送的文件*/
306buffer=newbyte[fileLength];
307if((flag=RecvData(socket,buffer,outTime))==0){
308fs.Write(buffer,0,(int)fileLength);
309}

310}

311else{/**//*循环读取网络数据,并写入文件*/
312intrcvLen=maxBufferLength;
313longleftLen=fileLength;//剩下未写入的数据
314buffer=newbyte[rcvLen];
315
316while(leftLen!=0){
317if((flag=RecvData(socket,buffer,outTime))<0){
318break;
319}

320fs.Write(buffer,0,rcvLen);
321leftLen-=rcvLen;
322rcvLen=(maxBufferLength<leftLen)?maxBufferLength:((int)leftLen);
323}

324}

325fs.Close();
326}

327catch(IOExceptione){
328Log.WriteLog(e);
329flag=-4;
330}

331returnflag;
332}

333
334/**////<summary>
335///接收远程主机发送的文件
336///</summary>
337///<paramname="socket">待接收数据且已经连接到远程主机的socket</param>
338///<paramname="fileName">保存接收到的数据的文件名</param>
339///<paramname="fileLength">待接收的文件的长度</param>
340///<returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>

341publicstaticintRecvFile(Socketsocket,stringfileName,longfileLength){
342returnRecvFile(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///<addname="MagicTraceSwitch"value="3"/>
16///</switches>
17///<traceautoflush="true"indentsize="4">
18///<listeners>
19///<addname="myListener"type="System.Diagnostics.TextWriterTraceListener"initializeData="myListener.log"/>
20///<removetype="System.Diagnostics.DefaultTraceListener"/>
21///</listeners>
22///</trace>
23///</system.diagnostics>
24///</configuration>
25///其中的initializeData="myListener.log",替换为自己的日志文件名称
26///</remarks>

27publicclassLog
28{
29privateLog(){
30}

31
32publicstaticvoidWriteLog(Exceptione){
33Debug.WriteLine(DateTime.Now.ToString()+""+e.Message+"["+e.StackTrace+"]");
34}

35
36publicstaticvoidWriteLog(stringmessage,stringsourceFile){
37Debug.WriteLine(DateTime.Now.ToString()+""+message+"["+sourceFile+"]");
38}

39
40publicstaticvoidWriteLog(stringmessage){
41Debug.WriteLine(DateTime.Now.ToString()+""+message);
42}

43}

44}

45

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值