• .Net socket服务器编程之为何也高效


    说到Socket编程,肯定大部分人举手c,c++。可惜现在已没有机会去追随并达到写服务器的水平,所以将就下还是考虑c#版的Socket服务器吧。

    经过一番查询,试用。一些数据和事实还是浮出水面,同时对c#版的服务器也有很大信心,下面慢慢列出。

    基础知识:

    1,首先socket按平台来分有两种一种是源自unix的和源自微软平台的winsock,句资料显示,winsock借鉴unix下的socket。

    2,从编程模式来看有两种,同步和异步

    3,按tcp协议又有短链接,长链接。

    在unix中,socket也称为网络文件描述符,在window下可视为一个特殊的i/o句柄,这些都是系统资源。每个来自网络的请求都需要socket资源去处理。提高这些资源的利用率就达到了提高服务器性能的目的。指导思想有:异步,重用,多线程,线程池。而融合了这些思想的则是IOCP模型。

    借用这个哥们的研究介绍下IOCP

    1) 使用IOCP模型编程的优点
           ① 帮助维持重复使用的内存池。(与重叠I/O技术有关)
           ② 去除删除线程创建/终结负担。
           ③ 利于管理,分配线程,控制并发,最小化的线程上下文切换。
           ④ 优化线程调度,提高CPU和内存缓冲的命中率。

    2) 使用IOCP模型编程汲及到的知识点(无先后顺序)
           ① 同步与异步
           ② 阻塞与非阻塞
           ③ 重叠I/O技术
           ④ 多线程
           ⑤ 栈、队列这两种基本的数据结构

    .Net下的socket编程:

    回到.Net,win32下有种技术叫做 Overlapped I/O,解释为:OVERLAPPED I/O是WIN32的一项技术, 你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内部正是以线程来I/O完成OVERLAPPED I/O。你可以获得线程的所有利益,而不需付出什么痛苦的代价。也就是说,OVERLAPPED主要是设置异步I/O操作,异步I/O操作是指应用程序可以在后台读或者写数据,而在前台做其他事情。OVERLAPPED 是winddows下的一种结构体,在c,c++中和.net中的不一样。CLR 中的 Overlapped 对象可以有效封装用于管理异步 I/O 操作的本机 Windows OVERLAPPED 结构。每个进行中的 Socket 异步 I/O 操作中都有一个 Overlapped 对象实例。在MSDN一篇杂志中宣城从3.5开始,可以拥有可以拥有 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 对象的属性提供。最后,需要使用事件处理程序回调完成方法。
     
    基于以上基础知识,感觉完全有信心使用c#版的socket服务器。目前已经选用了SuperSocket,使用简单,官方已列出大干比较有名的使用者。博客园好像也有人推荐自己公司的产品。看上去都不不错的样子。
    题外话,会写c,c++ socket服务器真爽啊,有猎头开出40w以上职位,可惜胜任不了。
  • 相关阅读:
    php -- php数组相关函数
    php -- 数组排序
    php -- in_array函数
    php -- 魔术方法 之 删除属性:__unset()
    无符号整型与有符号整型相运算规则
    N个节点的二叉树有多少种形态
    getopt_long
    typedef
    约瑟夫环问题算法(M)
    C语言基础
  • 原文地址:https://www.cnblogs.com/wusong/p/4211199.html
Copyright © 2020-2023  润新知