.NET3.5中的高性能 Socket API
转载:http://www.cnblogs.com/TianFang/archive/2007/11/09/954730.html
在 .NET Framework 2.0 版本中,System.Net.Sockets 命名空间提供了一个几乎拥有 Windows® WinSock Win32® API 的所有功能的 Socket 类。该功能所属的类包含为托管代码开发人员设计的各种方法和属性。在 Socket 上,有一组包括 Send 和 Receive 在内的同步方法,具备针对各种情况的参数重载。这些同步方法不仅易于使用,而且非常适合于使用套接字的简单网络任务。Socket 上还有一组基于异步编程模型 (APM) 的异步方法,APM 在 .NET Framework 中非常普遍(有关详细信息,请参阅 msdn.microsoft.com/msdnmag/issues/07/03/ConcurrentAffairs)。这些异步方法让 Socket 类的异步使用相对简单,而且还提供了一种方法来处理许多套接字,或处理在许多套接字上进行的多个发送和接收操作。
2.0 版本的 Socket 类适合多种需要使用网络套接字的客户端应用程序,以及一些服务器和服务类型的应用程序。遗憾的是,一些服务应用程序方案不适用于 2.0 版本的 Socket 类,却和直接使用 Windows WinSock API 的本机语言相容。2.0 版本的 Socket 类的主要问题是它不仅在分配必要的基础对象以便在大量套接字上同时保持 I/O 操作时需要占用过多的 CPU 循环,而且在执行单个套接字 I/O 操作时也同样如此。
凭借 .NET Framework 3.5,公共语言运行时 (CLR) 便可以更有效地同时管理大量的 Overlapped 对象。CLR 中的 Overlapped 对象可以有效封装用于管理异步 I/O 操作的本机 Windows OVERLAPPED 结构。每个进行中的 Socket 异步 I/O 操作中都有一个 Overlapped 对象实例。现在可以拥有 6 万个甚至更多的连接套接字,并同时在每个套接字上保持一个挂起的异步接收 I/O 操作。
2.0 版本的 Socket 类使用 Windows I/O 完成端口来完成异步 I/O 操作。这使应用程序可以轻易地扩展到大量的打开的套接字。.NET Framework 实现了 System.Threading.ThreadPool 类,该类提供可读取完成端口并完成异步 I/O 操作的完成线程。在开发即将发布的 3.5 版本的 .NET Framework 的过程中,我们将大量的精力放在了消除代码路径中的开销上,包括读取完成端口和调用应用程序的完成代理或在 IAsyncResult 对象中发出 I/O 完成事件对象信号之间。
.NET Framework 中的 APM 也称为 Begin/End 模式。这是因为会调用 Begin 方法来启动异步操作,然后返回一个 IAsyncResult 对象。可以选择将一个代理作为参数提供给 Begin 方法,异步操作完成时会调用该方法。或者,一个线程可以等待 IAsyncResult.AsyncWaitHandle。当回调被调用或发出等待信号时,就会调用 End 方法来获取异步操作的结果。这种模式很灵活,使用相对简单,在 .NET Framework 中非常常见。
但是,您必须注意,如果进行大量异步套接字操作,是要付出代价的。针对每次操作,都必须创建一个 IAsyncResult 对象,而且该对象不能被重复使用。由于大量使用对象分配和垃圾收集,这会影响性能。为了解决这个问题,新版本提供了另一个使用套接字上执行异步 I/O 的方法模式。这种新模式并不要求为每个套接字操作分配操作上下文对象。
我们没有创建全新的模式,而只是采用现有模式并做了一个基本更改。现在,在 Socket 类中有了一些方法,它们使用基于事件的完成模型的变体。在 2.0 版本中,您可以使用下列代码在某个套接字上启动异步发送操作:
void OnSendCompletion(IAsyncResult ar) { }
IAsyncResult ar = socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, OnSendCompletion, state);
在新版本中,您还可以实现:
void OnSendCompletion(object src, SocketAsyncEventArgs sae) { }
SocketAsyncEventArgs sae = new SocketAsyncEventArgs();
sae.Completed += OnSendCompletion;
sae.SetBuffer(buffer, 0, buffer.Length);
socket.SendAsync(sae);
这里有一些明显的差别。封装操作上下文的是一个 SocketAsyncEventArgs 对象,而不是 IAsyncResult 对象。该应用程序创建并管理(甚至可以重复使用)SocketAsyncEventArgs 对象。套接字操作的所有参数都由 SocketAsyncEventArgs 对象的属性和方法指定。完成状态也由 SocketAsyncEventArgs 对象的属性提供。最后,需要使用事件处理程序回调完成方法。
所有这些更改都显著改进了 .NET Framework 3.5 中 System.Net.Sockets 类的性能和可伸缩性。现有应用程序可以自动实现其中的两项改进。第三项改进,即新型 Socket 方法,只能通过修改应用程序而得到使用,但这些方法都能为基于套接字的高要求应用程序提供更理想的可伸缩性。
一个Tcp版的EchoServer的示例如下:
class EchoServer
{
Socket server;
public EchoServer(IPEndPoint localPoint)
{
server = new Socket(localPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
server.Bind(localPoint);
server.Listen(5);
accept_async();
}
private void accept_async()
{
var accept = new SocketAsyncEventArgs();
accept.Completed += accept_Completed;
server.AcceptAsync(accept);
}
void accept_Completed(object sender, SocketAsyncEventArgs e)
{
accept_async();
var client = e.AcceptSocket;
e.Completed -= accept_Completed;
e.Completed += receive_Completed;
var buffer = new byte[1024];
e.SetBuffer(buffer, 0, buffer.Length);
client.ReceiveAsync(e);
}
void receive_Completed(object sender, SocketAsyncEventArgs e)
{
var client = sender as Socket;
if (e.BytesTransferred == 0)
{
Console.WriteLine("socket is closed");
client.Close();
}
else
{
client.Send(e.Buffer, e.BytesTransferred, SocketFlags.None);
client.ReceiveAsync(e);
}
}
}
参考文章:http://msdn.microsoft.com/zh-cn/magazine/cc163356.aspx
.NET3.5中的高性能 Socket API的更多相关文章
- Java实现网络聊天中使用的socket API与Linux socket API之间的关系
尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码.代码如下: package project1; import java.awt.*; import ja ...
- Pipelines - .NET中的新IO API指引(三) 边看边记
Pipelines - .NET中的新IO API指引 作者 marcgravell 原文 此系列前两篇网上已有的译文 Pipelines - .NET中的新IO API指引(一) Pipeline ...
- UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认
在socket系统调用中,如何完成三次握手和四次挥手: SOCK_DGRAM即UDP中的connect操作知识在内核中注册对方机器的IP和PORT信息,并没有建立连接的过程,即没有发包,close也不 ...
- 使用Beetle简单构建高性能Socket tcp应用
beetle是基于c#编写的高性能Socket tcp组件,它基于SocketAsyncEventArgs的实现并提供了发送队列和接收队列的支持,可以根据情况灵活地设置1-N个发送队列和接收队列.除了 ...
- (IOCP)-C#高性能Socket服务器的实现
C#高性能Socket服务器的实现(IOCP) https://www.jianshu.com/p/c65c0eb59f22 引言 我一直在探寻一个高性能的Socket客户端代码.以前,我使用Sock ...
- JNI 和 socket api
1.JavaVM 和 JNIEnvJNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立.JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线程 ...
- LwIP - raw/callback API、协议栈API(sequential API)、BSD API(或者说 SOCKET API)
1.使用raw/callback API编程,用户编程的方法是向内核注册各种自定义的回调函数,回调函数是与内核实现交换的唯一方式. recv_udp, accept_function, sent_tc ...
- socket编程 ------ BSD socket API
伯克利套接字(Berkeley sockets),也称为BSD Socket.伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信. BSD Socket的应用 ...
- Python Socket API 笔记
将上节中的C#该成Python版的容易程度大大超出了我的意料之外.从来没有发现,仅仅用灰尘简单的几句话就实现了该程序的主要功能,可见python的简易和强大之处.这里先对SocketAPI 做一下总结 ...
随机推荐
- C++实现RTMP协议发送H.264编码及AAC编码的音视频(转)
C++实现RTMP协议发送H.264编码及AAC编码的音视频(转) RTMP(Real Time Messaging Protocol)是专门用来传输音视频数据的流媒体协议,最初由Macromedia ...
- POJ2676 Sudoku(dfs)
题目链接. 题目大意: 就是数独游戏.横竖,每一个9宫方块,必须有1~9,且不重复. 分析: 直接DFS.一开始在原图上搜,会TLE.把要补全的空格,放入数组,这样就不用遍历整个图寻找要填的空格了. ...
- 【转】iOS开发:开发证书知识点总结
原文网址:http://www.jianshu.com/p/9c166a5e4930 1. Error: An App ID with identifier "*" is not ...
- 【转】iOS Provisioning Profile(Certificate)与Code Signing详解 -- 待看
原文网址:http://blog.sina.com.cn/s/blog_82c8198f0102vy4j.html 引言 关于开发证书配置(Certificates & Identifiers ...
- MySQL数据库的优化-运维架构师必会高薪技能,笔者近六年来一线城市工作实战经验
原文地址:http://liangweilinux.blog.51cto.com/8340258/1728131 首先在此感谢下我的老师年一线实战经验,我当然不能和我的老师平起平坐,得到老师三分之一的 ...
- ASP.NET MVC 中将FormCollection与实体间转换方法 (转)
将Action动作中传递的FormCollection转变成对应的实体,可以使用Controller的TryUpdateModel()方法. [HttpPost] public ActionResul ...
- 是C太傻逼?还是C++不够傻逼;
1,类对象宏object-like macro,类函数宏macro中不允许有空格,名称遵循变量名命名规则; 同样是笔记,顺序条理无,看管随意,意在与神会,不解释则会意此为深,随意则会意此乃为度...望 ...
- hdoj 1698 Just a Hook【线段树区间修改】
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdoj 1068 Girls and Boys【匈牙利算法+最大独立集】
Girls and Boys Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- Struct2 拦截器
拦截器的整个过程 程序是在执行Action之前调用的拦截器,整个过程是这样子的 这里面注意两个问题: public void serviceAction(HttpServletRequest requ ...