`
v5qqcom
  • 浏览: 1285412 次
文章分类
社区版块
存档分类
最新评论

对Socket常用方法的封装

 
阅读更多

在一个blog上看到的好帖,写了一个对网络 socket 进行封装的类,主要是在异步阻塞模式下进行数据、文件的发送的发送和接收,都是静态方法。代码如下:
1usingSystem;
2usingSystem.Net;
3usingSystem.Net.Sockets;
4usingSystem.IO;
5usingLogDll;
6
7namespaceNetDll
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#defineDEBUG
2
3usingSystem;
4usingSystem.Diagnostics;
5
6namespaceLogDll
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


分享到:
评论

相关推荐

    Socket异步通信封装

    Socket异步通信封装 使用Begin...End...异步方法 该类库常用类: TCPClient TCPListener TCPListenerClient UDPService

    使用IOCP完成端口和SOCKET封装的成熟异步TCP类

    使用IOCP完成端口和SOCKET封装的异步TCP类。 支持客户端和服务器的常用TCP接口:绑定Bind、监听Listen、接收Recv、连接Conn、发送Send、关闭Close。所有接口均使用异步回调的方式处理,内部实现使用Windows下性能...

    SOP SOIC SOT SSOPBGA QFN QFP芯片常用AD封装库480个合集.zip

    SOP SOIC SOT SSOPBGA QFN QFP芯片常用AD封装库480个合集,封装型号列表如下: SSO48 SSO56 SSOP-8 SSOP-24-0.65 SSOP-24-1.0 SSOP-28 SSOP8 SSOP14 SSOP16 SSOP24 SSOP24_L SSOP28 TO-92B TO-126 TO-220 TO-252 TO-...

    C#中一个高性能异步socket封装库的实现思路分享

    我搜集了大量资料,完成了对异步socket的封装。此库已用稳定高效的运行几个月。 纵观网上的资料,我还没有遇到一个满意的封装库。许多文章把数据收发和协议处理杂糅在一块,代码非常难懂,也无法扩展。 在

    BGA QFN QFP SOP SOIC SOT SSOP芯片常用AD封装库484个合集.PcbLib

    BGA QFN QFP SOP SOIC SOT SSOP芯片常用AD封装库484个合集.PcbLib,可以直接用于你的硬件设计: Component Count : 484 Component Name ----------------------------------------------- BGA16X16-B288 BGA18X18-B...

    让你的HpSocket Pull支持同步(应答式)操作

    HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中[1] 。为了让使用者能方便快速地学习和使用 HP-Socket ,...

    常用的PROTEL99SE元件库封装库芯片库接插件库739个(PROTEL封装库).lib

    常用的PROTEL99SE元件库封装库芯片库接插件库739个(PROTEL封装库),Component Count : 739 Component Name ----------------------------------------------- 0.5INCH-DISP 0.8INCH-DISP 1_27_2_40 1.0INCH-DISP...

    QFN QFP SOP SOIC SOT SSOP BGA常用芯片protel99se封装(480个合集).zip

    QFN QFP SOP SOIC SOT SSOP BGA常用芯片protel99se封装,共480个, 详细列表如下: BGA144 BGA169 BGA196C65P14X14_1000X1000X152 BGA289 BGA337 BGA624_0P8_21X21 BGA676X26 LQFP_64_0.5 LQFP-48 LQFP-64_M LQFP-...

    电阻电容常用器件pcb封装protel99se封装库316个合集.zip

    电阻电容常用器件pcb封装protel99se封装库316个合集,DDB工程文件封装库,已在项目中使用,可以做为你的设计参考。 Component Count : 316 Component Name ----------------------------------------------- ...

    socket演示程序

    这个测试工程中对Socket封装的类的文件: Soc.h Soc.cpp 网络传输封装类 SocMesWnd 异步网络传输时,接收网络消息的窗体 该DEMO演示了以下技术: 1、CTCPServe、CTCPClient Tcp异步传输,含TCP客户端与...

    Micro-USB A型D型USB-Mini 接口等各类USB接口 3D封装库(STEP后缀)文件.zip

    Micro-USB A型D型USB-Mini 接口等各类USB接口 3D封装库(STEP后缀)文件: kma-smt-5s-s-30tr.STEP kusb-sl-as1n-w-kycon.STEP KUSBVX-AS2N-W.STEP MICRO-USB-5pinmsbr-18.stp Micro-USB-DIP.STEP Micro-USB-SMD....

    互斥锁+共享内存封装库,实现进程间通讯(Linux)

    Linux下提供了多种共享内存的通讯机制,常用的就是socket,但是socket通讯使用简单,但性能不佳,最优的方式还是共享内存方式。本章分享封装库,的就是基于共享内存实现的。 本分享库是基于Ubuntu16.04编译的,如需...

    HttpInterface:Windows上C++封装的HTTP库,包含三种实现模式(WinInet、WinHttp、socket)

    HttpInterface:Windows上C++封装的HTTP库,包含三种实现模式(WinInet、WinHttp、socket)主要实现了HTTP的get\post方法,下载到内存、下载到本地文件,回调下载进度等接口 测试程序中展现了常用的几个方法。...

    android socket网络通信编程实例

    再此说明一下:Socket仅仅是对TCP、UDP网络接口的封装,不涉及上层协议。    .Socket 客户端连接使用的TCP socket  .DatagramSocket 客户端和服务端共同使用的UDP socket  .ServerSocket 服务端TCP socket监听...

    个人封装类

    个人封装了一个类库 Data下是基于企业库的一个常用基类 Excel下是Excel封装类 Socket的两个包下是两个套接字封装类 Tools下一个ini文件操作类,一个验证类 WinForm下是一个cs分页类

    让你的HpSocket Pull支持同步(应答式)操作-易语言

    HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中[1]。 为了让使用者能方便快速地学习和使用 HP-Socket ,...

    Unity 最好用的网络库 Best HTTP2 2.6.2

    因此我们可以自己封装Http协议来满足更多的需要。在Unity游戏里使用Http协议的情况很常见,因为它操作简单,便于实现,经常用在登陆等场景下,还例如下载上传一些资源。如果想要实现进一步的控制,就要使用Socket并...

    易语言-让你的HpSocket Pull支持同步(应答式)操作

    HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中[1] 。 为了让使用者能方便快速地学习和使用 HP-Socket ,...

Global site tag (gtag.js) - Google Analytics