转载: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的更多相关文章

  1. Java实现网络聊天中使用的socket API与Linux socket API之间的关系

    尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码.代码如下: package project1; import java.awt.*; import ja ...

  2. Pipelines - .NET中的新IO API指引(三) 边看边记

    Pipelines - .NET中的新IO API指引 作者 marcgravell  原文 此系列前两篇网上已有的译文 Pipelines - .NET中的新IO API指引(一) Pipeline ...

  3. UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认

    在socket系统调用中,如何完成三次握手和四次挥手: SOCK_DGRAM即UDP中的connect操作知识在内核中注册对方机器的IP和PORT信息,并没有建立连接的过程,即没有发包,close也不 ...

  4. 使用Beetle简单构建高性能Socket tcp应用

    beetle是基于c#编写的高性能Socket tcp组件,它基于SocketAsyncEventArgs的实现并提供了发送队列和接收队列的支持,可以根据情况灵活地设置1-N个发送队列和接收队列.除了 ...

  5. (IOCP)-C#高性能Socket服务器的实现

    C#高性能Socket服务器的实现(IOCP) https://www.jianshu.com/p/c65c0eb59f22 引言 我一直在探寻一个高性能的Socket客户端代码.以前,我使用Sock ...

  6. JNI 和 socket api

    1.JavaVM 和 JNIEnvJNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立.JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线程 ...

  7. LwIP - raw/callback API、协议栈API(sequential API)、BSD API(或者说 SOCKET API)

    1.使用raw/callback API编程,用户编程的方法是向内核注册各种自定义的回调函数,回调函数是与内核实现交换的唯一方式. recv_udp, accept_function, sent_tc ...

  8. socket编程 ------ BSD socket API

    伯克利套接字(Berkeley sockets),也称为BSD Socket.伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信. BSD Socket的应用 ...

  9. Python Socket API 笔记

    将上节中的C#该成Python版的容易程度大大超出了我的意料之外.从来没有发现,仅仅用灰尘简单的几句话就实现了该程序的主要功能,可见python的简易和强大之处.这里先对SocketAPI 做一下总结 ...

随机推荐

  1. BZOJ_1565_[NOI2009]_植物大战僵尸_(Tarjan+最大流+最大权闭合图)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1565 n*m的矩阵,可以种植植物,僵尸从图的右边进入吃植物.前面的植物可以保护后面的植物,还有 ...

  2. 在Eclipse中安装和使用TFS插件

    在Eclipse中安装插件的方法其实都一样,安装TFS的步骤如下: 下载TFS插件.你可以到微软的下载中心,下载TFS插件TFSEclipsePlugin-UpdateSiteArchive-10.0 ...

  3. CMD删除Mysql 服务

    用sc.exe这个命令可以删除Windows系统服务 开始 —> 运行 —> cmd.exe,然后输入sc就可以看到了. 使用办法很简单: sc delete "服务名" ...

  4. 分布式基础通信协议:paxos,totem和gossip

    转:http://blog.csdn.net/cloudresearch/article/details/23127985 背景: 在分布式中,最难解决的一个问题就是多个节点间数据同步问题.为了解决这 ...

  5. vijosP1006 晴天小猪历险记之Hill

    vijosP1006 晴天小猪历险记之Hill 链接:https://vijos.org/p/1006 [思路] 图上DP. 这个题的递推顺序是关键.先从上一行得到最小值,然后从本行比较最小值,注意本 ...

  6. 基于UDP协议的控制台聊天

    这几天学了java的网络编程弄出一个基于UDP协议的聊天工具 功能 添加并且备注好友(输入对方的ip) 删除好友 查看好友列表 用java写的控制台程序导出可执行程序后不能双击打开 还需要些一个脚本文 ...

  7. html自定义checkbox、radio、select —— select篇

    上一篇<html自定义checkbox.radio.select —— checkbox.radio篇>介绍了我们是怎么将 html 自带的 checkbox.radio 改成我们自定义的 ...

  8. 3 weekend110的shuffle机制 + mr程序的组件全貌

    前面,讲到了hadoop的序列化机制,mr程序开发,自定义排序,自定义分组. 有多少个reduce的并发任务数可以控制,但有多少个map的并发任务数还没 缓存,分组,排序,转发,这些都是mr的shuf ...

  9. Linux中如何新建用户

    对于一般用户来说,主目录(home directory)是硬盘上唯一可以原来写东西的地方.一般的路径名是/home/login_user_name. 主目录用于存储各种用户文件:设置文件,程序配置文件 ...

  10. phpnow下mysqli加载不了的问题

    用了phpnow也有蛮长一段时间了.一直感觉还不错,不过就是差点把手动配置apache/php/mysql环境的方法都给忘了. 这几天一直都在找crm系统,可惜没有几个满意的.今天逛上了weberp这 ...