实现基于事件通知的.Net套接字

以前学过MFC,我用过的它里面的包装Winsock的两个类CSocket和CAsyncSocket,我一直觉得它哪个事件通知的功能比较不错,特别是在连接的两方收发数据没有一定的规律的时候比较有用,虽然不用它的事件通知也可以实现功能,但是你需要循环检测套接字的状态或者阻塞等待,如果每次都要做这些琐碎的工作岂不是很麻烦,于是我就想对这些功能作一次封装。当然在.net里面采用delegate和event是最好的选择了。下面就是我实现的一些细节:

先讲一下思路:其实这个还是很简单了,估计高手们会不屑一顾了^_^。当套接字开始工作,比如开始监听、开始连接的时候,启动一个线程不停的检测套接字的状态,当某一事件的状态条件满足时就触发此事件,要知道具体检测套接字状态的方法,请往下看。

平常用套接字编成的时候可能需要用到的功能就是:连接成功或者失败的通知、在监听的套接字上有挂起的连接的通知、有数据可以接受的通知、套接字关闭的通知、还有套接字空闲可以发送数据的通知等,我也就使对上面几个功能作了封装,不过我觉得最后面一个功能用处不大???

我的Socket类是从System.Net.Sockets.Socket继承下来的,类名TcpEventSocket,实现如下:

先申明事件的委托类型,具体看代码

public delegate void AcceptConnectionHandler();

public delegate void ConnectCompletedHandler(bool connected); //connected表明连接成功与否

public delegate void DataCanSendHandler();

public delegate void DataCanReceiveHandler(int buffersize); //当前可以接受的数据量

public delegate void SocketClosedHandler();

这些类型具体什么意思应该能看出来吧,另外还要申明对应的事件

public event AcceptConnectionHandler AcceptConnection;

public event ConnectCompletedHandler ConnectCompleted;

public event DataCanSendHandler DataCanSend;

public event DataCanReceiveHandler DataCanReceive;

public event SocketClosedHandler SocketClosed;

另外加了几个虚方法,这几个方法用来触发事件

protected virtual void OnAcceptConnection();
protected virtual void OnConnectCompleted(bool connected)

protected virtual void OnDataCanSend()
protected virtual void OnDataCanReceive(int buffersize)

protected virtual void OnSocketClosed()

为了在适当的事机启动检测线程,我重写了几个基类的方法:

new public void Listen(int backlog)

{

base.Listen(backlog);

sockState = SocketState.Listenning;

if (!checkThread.IsAlive)

checkThread.Start();

}

new public void Connect(EndPoint remoteEP)

{

try

{

base.Connect(remoteEP);

this.Blocking = false; //设置非阻塞状态,以便事件通知的效率

if (!checkThread.IsAlive)

checkThread.Start();

}

catch(SocketException)

{

OnConnectCompleted(false);

}

}

这两个方法实际编成中都应该首先被调用的,所以有他们启动检测线程比较合适,另外线程启动了必然也要中止,于是我重写了Close方法

new public void Close()

{

if(checkThread.IsAlive) //先中止线程再关闭连接

checkThread.Abort();

base.Close();

sockState = SocketState.Disconnected;

OnSocketClosed();

}

于是剩下的工作就是怎么检测套接字了,Socket类有个Select的静态方法,它可以检测很多套接字的状态,不过这里只需要检测一个,所以直接用Socket的Poll方法,Poll的具体用法可以看MSDN,我这里用代码说明我对套接字的检测方法

while(true) //循环检查

{

if (sockState == SocketState.Disconnected) //如果当前没有连接

{

if (Poll(500, SelectMode.SelectWrite))

OnConnectCompleted(true); //如果为可写状态,则表示连接成功

}

else if(sockState == SocketState.Listenning)

{

if (Poll(500, SelectMode.SelectRead)) //如果在监听状态发现套接字有数据可读则表示已经有人连接上来可以调用Accept接受连接

OnAcceptConnection();

}

else //这里sockState = SocketState.Connected

{

if (Poll(500, SelectMode.SelectWrite)) //如果有可写状态则表示可以发送数据

OnDataCanSend();

if (Poll(500, SelectMode.SelectRead)) //如果有可读状态

{

if (Available > 0) //如果有数据可读表示可以调用Receive接受数据

OnDataCanReceive(Available);

else

{

OnSocketClosed(); //没数据可读表示连接已经关闭

break;

}

}

}

//如果没有连接并且有错误状态,则连接失败

if (sockState == SocketState.Disconnected && Poll(500, SelectMode.SelectError))

OnConnectCompleted(false);

}

这里的OnXXX方法就是执行事件通知的方法,并且派生类中可以重载这些方法直接获得事件通知而不需要挂界别的事件通知处理函数(类似于MFC的OnAccept等虚函数)。不过派生的函数集的调用基类的相应方法哦。很可惜没有重写Socket.Accept方法,让它返回一个TcpEventSocket,这样应该就比较完整了,只可惜我不知道怎么做^_^,如果谁知道的话欢迎指教。

事件通知机制已经基本完成,所缺乏的只是大量的测试(我做了几下最简单的测试,惭愧!!^_^)

如果有问题请联系 yzx110@bit.edu.cn

时间: 2024-12-21 23:51:41

实现基于事件通知的.Net套接字的相关文章

实现基于事件通知的.Net套接字_实用技巧

  以前学过MFC,我用过的它里面的包装Winsock的两个类CSocket和CAsyncSocket,我一直觉得它哪个事件通知的功能比较不错,特别是在连接的两方收发数据没有一定的规律的时候比较有用,虽然不用它的事件通知也可以实现功能,但是你需要循环检测套接字的状态或者阻塞等待,如果每次都要做这些琐碎的工作岂不是很麻烦,于是我就想对这些功能作一次封装.当然在.net里面采用delegate和event是最好的选择了.下面就是我实现的一些细节:   先讲一下思路:其实这个还是很简单了,估计高手们会

基于多线程的客户端/服务器套接字类

这篇文章主要介绍如何设计基于多线程的客户端/服务器套接字(socket)类.开发者/设计者可以根据具体的 需要决定是否选用另外的线程.在网络上有许多其它的套接字类,但是没有一个能够向这个类一样为你的应用程序 提供回调功能(事件监测).本文设计的类能够为你提供如下的事件监测:完成建立链接.放弃链接.链接失败和 接收数据(包括0字节数据包). 描述: 本文提供一种新的,同时支持TCP和UDP通讯的套接字类,与你可能在本站或其它地方发现的套接字编程文章相 比,本文设计的类有很多优点.首先,这个类没有像

Linux下套接字详解(五)----基于fork多进程的TCP套接字(阻塞/同步/并发)

简介 一个简单的改进方案是在服务器端使用多线程(或多进程).多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接.具体使用多进程还是多线程,并没有一个特定的模式.传统意义上,进程的开销要远远大于线程,所以如果需要同时为较多的客户机提供服务,则不推荐使用多进程:如果单个服务执行体需要消耗较多的CPU资源,譬如需要进行大规模或长时间的数据运算或文件访问,则进程较为安全.通常,使用pthread_create ()创建新线程,fork()创建新进程

一个基于原始套接字的嗅探器

嗅探器这个代码我去年的时候就已经写过了,这个学期并不是非常忙,顺手复习网络,就又尝试着写了一遍. 其实在写嗅探器的时候,最主要的还是要将网卡设置为混杂模式.在此基础之上,对抓到的数据包进行分析. 这个是我写出来的效果图,目前只是方便于查看,连菜单都没添加: 左面的界面显示的是主机和主机之间的链接信息,而右面则是选中主机信息之间的数据交互情况. 我觉得我这个嗅探器应该是个失败品,或者说,没能够真正的将网卡设置为混杂模式.因为可以看到,上面的源地址全部都是本地主机地址,我在下载视频文件的时候,每秒几

[python] 专题七.网络编程之套接字Socket、TCP和UDP通信实例

        很早以前研究过C#和C++的网络通信,参考我的文章:                  C#网络编程之Tcp实现客户端和服务器聊天                 C#网络编程之套接字编程基础知识                 C#网络编程之使用Socket类Send.Receive方法的同步通讯        Python网络编程也类似.同时最近找工作笔试面试考察Socket套接字.TCP\UDP区别比较多,所以这篇文章主要精简了<Python核心编程(第二版)>第16章内

由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。(含服务端代码)

问题描述 演练一个Windows应用程序-聊天软件,分别有服务端和客户端问题是在服务端激发buttonStop_Click事件时出现"由于套接字没有连接并且(当使用一个sendto调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受."错误,不知道如何解决,麻烦高手帮帮我//下面是服务端代码usingSystem;usingSystem.Drawing;usingSystem.Collections;usingSystem.ComponentModel;usingSys

基于WEB的实时事件通知方案

基于 WEB 的实时事件通知方式大致有五种方案:HTTP拉取方式(pull),HTTP流,Long Polling,FlashXMLSocket方式,Java Applet. 首先说下Comet这个词,Comet这个词是最早由Alex Russell(DojoToolkit 的项目 Lead)提出的,称基于 HTTP 长连接.无须在浏览器端安装插件的"服务器推(Push)"技术为"Comet". 1. HTTP拉取方式(pull) 在这种传统的方法中,客户端以用户可

基于事件解析的SAX模型分析

SAX2解析器读XML文档,然后产生基于特殊符号的事件.SAX2解析器实际上并不为该文档在内存中创建一棵树结构,它序列的处理一个文档的内容并产生相关的事件. 比如,当你进行基于事件的编程的时候,你可以创建函数来响应用户定义的事件(比如OnClick事件).在利用SAX进行编程的时候,需要注意的是,是解析器而不是用户产生事件. 比如考虑下面一个简单的文档. <?xml version="1.0"?> <parts> <part>TurboWidget&

封装stream,在读写stream时提供事件通知

前阵子的工作涉及一些网络编程,使用了面向流的方式做传输数据.在代码过程中,遇到一个新需求就是要统计流量.其实最简单的办法就时在读写流的地方增加代码,把功能增加上去就可以.但是我觉得那样对我原理的代码框架影响较大,基于尽量不影响原来的代码的考虑,我想到了Decorator设计模式. 先把代码贴出来,在做解释吧:     以下为引用的内容: public class EventStream : Stream    {        public event EventHandler<FStreamD