CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  专题开发/技术/项目 >  网络通信

关于网络游戏的网络通讯有啥参考资料吗

楼主skull()2005-01-14 11:53:36 在 专题开发/技术/项目 / 网络通信 提问

我们公司现在准备为游戏写个网络引擎,我以前是搞图形的,网络部分没啥经验。  
  动手之前想看看网上能否收集到一些这方面的资料,少走弯路。  
  谢谢各位了。 问题点数:50、回复次数:2Top

1 楼netsys2(来电!)回复于 2005-01-17 10:28:35 得分 50

主  题:     [原创]理解I/O   Completion   Port    
  作  者:     nonocast   (如果没有如果)      
  等  级:          
  信   誉   值:     104    
  所属论坛:     专题开发   游戏开发    
  问题点数:     100    
  回复次数:     23    
  发表时间:     2004-1-13   12:31:26    
         
     
         
   
          欢迎阅读此篇IOCP教程。我将先给出IOCP的定义然后给出它的实现方法,最后剖析  
  一个Echo程序来为您拨开IOCP的谜云,除去你心中对IOCP的烦恼。OK,但我不能保证你  
  明白IOCP的一切,但我会尽我最大的努力。以下是我会在这篇文章中提到的相关技术:  
   
  ▲I/O端口  
  ▲同步/异步  
  ▲堵塞/非堵塞  
  ▲服务端/客户端  
  ▲多线程程序设计  
  ▲Winsock   API   2.0  
   
          这之前,我曾经开发过一个项目,其中一块需要网络支持,当时还考虑到了代码的  
  可移植性,只要使用select,connect,accept,listen,send还有recv,再加上几个#ifdef  
  的封装以用来处理Winsock和BSD套接字[socket]中间的不兼容性,一个网络子系统只用  
  了几个小时很少的代码就写出来了,至今还让我很回味。那以后很长时间也就没再碰了。  
          前些日子,我们策划做一个网络游戏,我主动承担下网络这一块,想想这还不是小  
  case,心里偷着乐啊。网络游戏好啊,网络游戏为成百上千的玩家提供了乐趣和令人着秘  
  的游戏体验,他们在线上互相战斗或是加入队伍去战胜共同的敌人。我信心满满的准备  
  开写我的网络,于是乎,发现过去的阻塞同步模式模式根本不能拿到一个巨量多玩家[MMP]  
  的架构中去,直接被否定掉了。于是乎,就有了IOCP,如果能过很轻易而举的搞掂IOCP,  
  也就不会有这篇教程了。下面请诸位跟随我进入正题。  
   
   
  什么是IOCP  
   
  先让我们看看对IOCP的评价  
   
    ▲   I/O完成端口可能是Win32提供的最复杂的内核对象。  
          [Advanced   Windows   3rd]   Jeffrey   Richter  
   
    ▲   这是[IOCP]实现高容量网络服务器的最佳方法。  
          [Windows   Sockets2.0:Write   Scalable   Winsock   Apps   Using   Completion   Ports]  
          Microsoft   Corporation  
   
    ▲   完成端口模型提供了最好的伸缩性。这个模型非常适用来处理数百乃至上千个套接字。  
          [Windows网络编程2nd]   Anthony   Jones   &   Jim   Ohlund   I/O   completion   ports  
   
    ▲   特别显得重要,因为它们是唯一适用于高负载服务器[必须同时维护许多连接线路]的  
  一个技术。Completion   ports利用一些线程,帮助平衡由I/O请求所引起的负载。这样的  
  架构特别适合用在SMP系统中产生的”scalable”服务器。  
        [Win32多线程程序设计]   Jim   Beveridge   &   Robert   Wiener    
   
          看来我们完全有理由相信IOCP是大型网络架构的首选。那IOCP到底是什么呢?  
          微软在Winsock2中引入了IOCP这一概念   。IOCP全称I/O   Completion   Port,中文译  
  为I/O完成端口。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与  
  使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起  
  来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口  
  就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。  
          这里我要对上面的一些概念略作补充,在解释[完成]两字之前,我想先简单的提一下  
  同步和异步这两个概念,逻辑上来讲做完一件事后再去做另一件事就是同步,而同时一起  
  做两件或两件以上事的话就是异步了。你也可以拿单线程和多线程来作比喻。但是我们一  
  定要将同步和堵塞,异步和非堵塞区分开来,所谓的堵塞函数诸如accept(…),当调用此  
  函数后,此时线程将挂起,直到操作系统来通知它,”HEY兄弟,有人连进来了”,那个挂  
  起的线程将继续进行工作,也就符合”生产者-消费者”模型。堵塞和同步看上去有两分相  
  似,但却是完全不同的概念。大家都知道I/O设备是个相对慢速的设备,不论打印机,调制  
  解调器,甚至硬盘,与CPU相比都是奇慢无比的,坐下来等I/O的完成是一件不甚明智的事  
  情,有时候数据的流动率非常惊人,把数据从你的文件服务器中以Ethernet速度搬走,其  
  速度可能高达每秒一百万字节,如果你尝试从文件服务器中读取100KB,在用户的眼光来看  
  几乎是瞬间完成,但是,要知道,你的线程执行这个命令,已经浪费了10个一百万次CPU周  
  期。所以说,我们一般使用另一个线程来进行I/O。重叠IO[overlapped   I/O]是Win32的一  
  项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这也就是[完成]的  
  含义。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内  
  部正是以线程来完成overlapped   I/O。你可以获得线程所有利益,而不需要付出什么痛苦  
  的代价。  
   
          完成端口中所谓的[端口]并不是我们在TCP/IP中所提到的端口,可以说是完全没有关  
  系。我到现在也没想通一个I/O设备[I/O   Device]和端口[IOCP中的Port]有什么关系。估计  
  这个端口也迷惑了不少人。IOCP只不过是用来进行读写操作,和文件I/O倒是有些类似。既  
  然是一个读写设备,我们所能要求它的只是在处理读与写上的高效。在文章的第三部分你会  
  轻而易举的发现IOCP设计的真正用意。  
   
   
          IOCP和网络又有什么关系?  
   
  int   main()  
  {  
  WSAStartup(MAKEWORD(2,   2),   &wsaData);  
  ListeningSocket   =   socket(AF_INET,   SOCK_STREAM,   0);  
  bind(ListeningSocket,   (SOCKADDR*)&ServerAddr,   sizeof(ServerAddr));  
  listen(ListeningSocket,   5);  
  int   nlistenAddrLen   =   sizeof(ClientAddr);  
  while(TRUE)  
  {  
  NewConnection   =   accept(ListeningSocket,   (SOCKADDR*)&ClientAddr,   &nlistenAddrLen);  
  HANDLE   hThread   =   CreateThread(NULL,   0,   ThreadFunc,   (void*)   NewConnection,   0,   &dwTreadId);  
  CloseHandle(hThread);  
  }  
  return   0;  
  }  
   
  Top

2 楼netsys2(来电!)回复于 2005-01-17 10:29:08 得分 0

相信只要写过网络的朋友,应该对这样的结构在熟悉不过了。accept后线程被挂起,等  
  待一个客户发出请求,而后创建新线程来处理请求。当新线程处理客户请求时,起初的线程  
  循环回去等待另一个客户请求。处理客户请求的线程处理完毕后终结。  
   
          在上述的并发模型中,对每个客户请求都创建了一个线程。其优点在于等待请求的线程  
  只需做很少的工作。大多数时间中,该线程在休眠[因为recv处于堵塞状态]。  
   
          但是当并发模型应用在服务器端[基于Windows   NT],Windows   NT小组注意到这些应用  
  程序的性能没有预料的那么高。特别的,处理很多同时的客户请求意味着很多线程并发地  
  运行在系统中。因为所有这些线程都是可运行的[没有被挂起和等待发生什么事],Microsoft  
  意识到NT内核花费了太多的时间来转换运行线程的上下文[Context],线程就没有得到很多  
  CPU时间来做它们的工作。  
   
          大家可能也都感觉到并行模型的瓶颈在于它为每一个客户请求都创建了一个新线程。创  
  建线程比起创建进程开销要小,但也远不是没有开销的。  
          我们不妨设想一下:如果事先开好N个线程,让它们在那hold[堵塞],然后可以将所有用  
  户的请求都投递到一个消息队列中去。然后那N个线程逐一从消息队列中去取出消息并加以处  
  理。就可以避免针对每一个用户请求都开线程。不仅减少了线程的资源,也提高了线程的利用  
  率。理论上很不错,你想我等泛泛之辈都能想出来的问题,Microsoft又怎会没有考虑到呢?!  
   
          这个问题的解决方法就是一个称为I/O完成端口的内核对象,他首次在Windows   NT3.5中  
  被引入。其实我们上面的构想应该就差不多是IOCP的设计机理。其实说穿了IOCP不就是一个消  
  息队列嘛!你说这和[端口]这两字有何联系。我的理解就是IOCP最多是应用程序和操作系统沟  
  通的一个接口罢了。至于IOCP的具体设计那我也很难说得上来,毕竟我没看过实现的代码,但  
  你完全可以进行模拟,只不过性能可能…,如果想深入理解IOCP,   Jeffrey   Ritchter的  
  Advanced   Windows   3rd其中第13章和第14张有很多宝贵的内容,你可以拿来窥视一下系统是  
  如何完成这一切的。  
   
       
          实现方法  
   
          Microsoft为IOCP提供了相应的API函数,主要的就两个,我们逐一的来看一下:  
   
  HANDLE   CreateIoCompletionPort   (  
      HANDLE   FileHandle,                                 //   handle   to   file  
      HANDLE   ExistingCompletionPort,           //   handle   to   I/O   completion   port  
      ULONG_PTR   CompletionKey,                 //   completion   key  
      DWORD   NumberOfConcurrentThreads   //   number   of   threads   to   execute   concurrently  
  );  
   
          在讨论各参数之前,首先要注意该函数实际用于两个截然不同的目的:  
   
          1.用于创建一个完成端口对象  
          2.将一个句柄[HANDLE]和完成端口关联到一起  
     
          在创建一个完成一个端口的时候,我们只需要填写一下NumberOfConcurrentThreads这个  
  参数就可以了。它告诉系统一个完成端口上同时允许运行的线程最大数。在默认情况下,所开  
  线程数和CPU数量相同,但经验给我们一个公式:  
   
          线程数   =   CPU数   *   2   +   2  
   
          要使完成端口有用,你必须把它同一个或多个设备相关联。这也是调用CreateIoCompletionPort  
  完成的。你要向该函数传递一个已有的完成端口的句柄,我们既然要处理网络事件,那也就是  
  将客户的socket作为HANDLE传进去。         和一个完成键[对你有意义的一个32位值,也就是一个指针,操作系统并不关心你传什么]。每当  
  你向端口关联一个设备时,系统向该完成端口的设备列表中加入一条信息纪录。  
   
  另一个API就是  
  BOOL   GetQueuedCompletionStatus(  
      HANDLE   CompletionPort,               //   handle   to   completion   port  
      LPDWORD   lpNumberOfBytes,           //   bytes   transferred  
      PULONG_PTR   lpCompletionKey,     //   file   completion   key  
      LPOVERLAPPED   *lpOverlapped,     //   buffer  
      DWORD   dwMilliseconds                   //   optional   timeout   value  
  );  
   
          第一个参数指出了线程要监视哪一个完成端口。很多服务应用程序只是使用一个I/O完成端  
  口,所有的I/O请求完成以后的通知都将发给该端口。简单的说,GetQueuedCompletionStatus  
  使调用线程挂起,直到指定的端口的I/O完成队列中出现了一项或直到超时。同I/O完成端口相  
  关联的第3个数据结构是使线程得到完成I/O项中的信息:传输的字节数,完成键和OVERLAPPED  
  结构的地址。该信息是通过传递给GetQueuedCompletionSatatus的lpdwNumberOfBytesTransferred,  
  lpdwCompletionKey和lpOverlapped参数返回给线程的。  
   
          根据到目前为止已经讲到的东西,首先来构建一个frame。下面为您说明了如何使用完成  
  端口来开发一个echo服务器。大致如下:  
  1.初始化Winsock  
  2.创建一个完成端口  
  3.根据服务器线程数创建一定量的线程数  
  4.准备好一个socket进行bind然后listen  
  5.进入循环accept等待客户请求  
  6.创建一个数据结构容纳socket和其他相关信息  
  7.将连进来的socket同完成端口相关联  
  8.投递一个准备接受的请求  
  以后就不断的重复5至8的过程  
   
          那好,我们用具体的代码来展示一下细节的操作。WOW,程序的代码若是贴在此处,实在大  
  煞风景,又不能CTRL+V还不能F7,如果大家需要源代码可以发信给我o_nono@163.net  
   
          至此文章也该告一段落了,我带着您做了一趟旋风般的旅游,游览了所谓的完成端口。  
          很多细节由于篇幅的关系无法细细道来。但希望这篇文章能带给您更多的思考。  
  如有任何问题,可以发信至o_nono@163.net。  
  Top

相关问题

  • 网络通讯?
  • 网络游戏
  • 求jasper 的参考资料
  • 求InterBase的中文参考资料
  • 索求InstallShield6的参考资料
  • 谁有STL中文参考资料啊?
  • 网络游戏的作弊???
  • 网络游戏与图片
  • 新手:网络通讯编程?
  • 怎么写网络游戏啊

关键词

  • .net
  • win32
  • 线程
  • 端口
  • 网络游戏
  • 函数
  • 客户
  • 操作系统
  • 应用程序
  • 代码

得分解答快速导航

  • 帖主:skull
  • netsys2

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo