• QQ 324186207群 enet交流技术,主要是为了研究tcp内部执行机制。欢迎大家增加探讨。小弟水平有限,翻译难免有误。



    http://enet.bespin.org

  • 解析enet 双向链表(无placement new) enet本身就已经局限了4095 在线人数   假设有10000人同一时候在线。enet使用list来维护每次收发,不断的销毁,释放内存,性能实在太低。

    enent写的根本不严谨,无论什么结构都存储双向链表,收一个包,我也须要去遍历,究竟获取某peer。

  • enet_host_service  每次事件抛出机制,实在太粗糙。说明enet
     很多其它偏向就是一个学习项目,假设大量数据传输,高并发,高负载,无法满足需求
  • 顺便提下。为何server好多地方不使用stl
  • 问题一:不能确定STL怎样管理内存。如果就依照STL默认的方法来管理内容。则server在长时间的分配和释放内存后,easy导致内存碎片。对server的稳定有影响。然而,如果没有阅读过STL的源代码。谁又能确切地得知STL是怎样管理内存的呢?尽管可以在STL中使用自己的分配器,又可以确认STL的某些部分不会在分配器之外进行内存分配呢?

    当然,内存管理问题不是STL带来的问题,不论什么server程序本身都要考虑这个问题。原因在极少有人去阅读STL的源代码。去了解STL的内部实现机理。由于不了解,所以怀疑。由于怀疑,所以不轻易使用。

    问题二:不能确定STL在海量数据下的表现。

    server一般都是海量的内存,为了提高性能大量数据保存在内存中。

    在很大的规模的数据下。STL一定可以满足稳定性和效率的需求吗?

    问题三:不能确定STL在多线程环境下的表现。

    以上的内存和规模的问题能够通过加深对STL的了解和測试来解决,可是多线程下的并发问题就不是那么easy攻克了。

    STL不是线程安全的。在多线程环境下。对STL容器的操作都要加锁来确保正确。然后。部分高性能的场合,须要对“读-读”条件下并发进行优化,以及某些锁无关的特殊条件能够不加锁,甚至是採用流行的RCU机制…………在这个倡导多核和并发的时代,STL显得有些落后了。

  • 传统的双向链表 普通情况我们套上 T *data
  • /*双链表结构*/
  • template<class T>
  • typedef struct node
  • {
  • T  *data;
  • struct node *prior;
  • struct node *next;
  • }DNode;
  • 下面enet双向链表结构,发现结构体内无T *data ,奇怪吧?那么我们数据存储到哪里?
  • #list.h
  • typedef struct _ENetListNode
  • {
  • struct _ENetListNode * next;
  • struct _ENetListNode * previous;
  • } ENetListNode;
  • typedef ENetListNode *
    ENetListIterator;
  • typedef struct _ENetList
  • {
  • ENetListNode sentinel;  //标记当前处于某个节点位置
  • } ENetList;
  • extern void enet_list_clear( ENetList * );
  • extern ENetListIterator enet_list_insert( ENetListIterator , void * );
  • extern void * enet_list_remove( ENetListIterator );
  • extern ENetListIterator enet_list_move( ENetListIterator, void *, void * );
  • extern size_t enet_list_size( ENetList * );
  • #define enet_list_begin(list) ((list) -> sentinel.next)
  • #define enet_list_end(list) (& (list) -> sentinel)
  • #define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
  • #define enet_list_next(iterator) ((iterator) -> next)
  • #define enet_list_previous(iterator) ((iterator) -> previous)
  • #define enet_list_front(list) ((void *) (list) -> sentinel.next)
  • #define enet_list_back(list) ((void *) (list) -> sentinel.previous)
  • #main.cpp
  • #define ENET_CALLBACK __cdecl
  • typedef struct _ENetCallbacks
  • {
  • void * ( ENET_CALLBACK * malloc ) ( size_t size );
  • void ( ENET_CALLBACK * free ) ( void * memory );
  • void ( ENET_CALLBACK * no_memory ) ( void );
  • } ENetCallbacks;
  • static ENetCallbacks callbacks = { malloc, free, abort };
  • void * enet_malloc( size_t size )
  • {
  • void * memory = callbacks.malloc( size );
  • if( memory == NULL )
  • callbacks.no_memory();
  • return memory;
  • }
  • void  enet_free( void * memory )
  • {
  • callbacks.free( memory );
  • }
  • struct ENetOutgoingCommand
  • {
  • ENetListNode list;
  • int a;
  • };
  • int main()
  • ENetOutgoingCommand *enet_outgoing;
  • ENetList enet_test;
  • enet_list_clear(&enet_test); //重置双向链表,将头指针和尾指针指向第一个空节点
  • enet_outgoing = (ENetOutgoingCommand *)enet_malloc( sizeof( ENetOutgoingCommand ) );
  • enet_outgoint->a = 100;
  • enet_list_insert( enet_list_end( &enet_test ), enet_outgoing ); //malloc
    数据插入到双向链表的尾部
  • ENetListIterator currentCommand;
  • currentCommand = enet_list_begin(&enet_test ); //这里取出双向链表头节点
  • while( currentCommand != enet_list_end( &enet_test ) ) //遍历链表
  • {
  • ENetOutgoingCommand * t1 = (ENetOutgoingCommand *)currentCommand;  //通过强转来获取数据
  • cout << t1->a << endl;
  • currentCommand = enet_list_next( currentCommand ); //获取下个节点
  • enet_list_remove( &t1->list ); //删除当前节点
  • enet_free( t1 );//删除内存,避免内存泄漏
  • while( Exit )
  • {
  • 開始server循环机制,这个循环设计非常的糟糕,每次一但server触发事件,会调用不同类型事件。

  • 解决的方法,每个while 我用队列收一把全部数据。然后在逐个遍历,这样添加了非常小延迟,可是提高了吞吐量。
  • 每次收到数据后。又从新  enet_protocol_send_outgoing_commands 開始检查第一个玩家,应该做个全局变量,存储当前遍历
          位置
  • ENetEvent event;
  • if( enet_host_service( server, &event, 1 ) )
  • {
  • switch( event.type )
  • {
  • case ENET_EVENT_TYPE_CONNECT:
  • {
  • Conneted( event.peer->connectID, event.peer->address.host, event.peer->address.port );
  • peersConn.Insert( event.peer->connectID, event.peer );
  • break;
  • }
  • case ENET_EVENT_TYPE_RECEIVE:
  • {
  • //bIdle = false;
  • //Recived( event.peer->connectID, event.packet->data, event.packet->dataLength );
  • break;
  • }
  • case ENET_EVENT_TYPE_DISCONNECT:
  • {
  • cout << "close client_fd" << endl;
  • //Disconneted( event.connectID );
  • break;
  • }
  • case ENET_EVENT_TYPE_PING:
  • {
  • cout << "enter reconnect:" << time( 0 ) << endl;
  • //ReConnection(event.peer->connectID);
  • break;
  • }
  • }
  • }
  • }
  • /** Waits for events on the host specified and shuttles packets between
  • the host and its peers.
  • @param host    host to service
  • @param event   an event structure where event details will be placed if one occurs
  • if event == NULL then no events will be delivered
  • 通向码农的道路(enet开源翻译计划 二)的更多相关文章

    1. 通向码农的道路(enet开源翻译计划 一)

      QQ 324186207群 enet交流技术.主要是为了研究tcp内部执行机制,欢迎大家增加探讨.小弟水平有限.翻译难免有误. . Features: ENet evolved specificall ...

    2. android码农神器 偷懒工具 android懒人框架 LoonAndroid 3 讲解

      LoonAndroid 3.0 Loonandroid是一个注解框架,不涉及任何UI效果,目的是一个功能一个方法,以方法为最小颗粒度对功能进行拆解.把功能傻瓜化,简单化,去掉重复性的代码,隐藏复杂的实 ...

    3. Android码农如何一个星期转为iOS码农(不忽悠)

      WeTest 导读 作为一个android客户端开发,如果你不懂点ios开发,怎么好意思说自己是客户端开发呢,本文讲解如何让android开发码农在一个星期上手IOS开发 --<记录自己IOS开 ...

    4. 拥抱Mac之码农篇

      拥抱Mac之码农篇 使用Mac大概两年时间.之前用着公司配的一台27寸的iMac.无奈机械硬盘严重拖慢速度,影响工作心情.于是入手Macbook Retina 13.这两年的开发工作所有在Mac上完毕 ...

    5. 【整理】待毕业.Net码农就业求职储备

      声明:本文题目来源于互联网,仅供即将从学校毕业的.Net码农(当然,我本人也是菜逼一个)学习之用.当然,学习了这些题目不一定会拿到offer,但是针对就业求职做些针对性的准备也是不错的.此外,除了技术 ...

    6. <开心一笑> 码农 黑客和2B程序员之间的区别

      笔记本电脑 码农: 黑客: 2B程序员: 求2的32次方: 码农: System.out.println(Math.pow(2, 32)); 黑客: System.out.println(1L< ...

    7. [2013 eoe移动开发者大会]靳岩:从码农到极客的升级之路

      (国内知名Android开发论坛 eoe开发者社区推荐:http://www.eoeandroid.com/) 前天,2013 eoe 移动开发者大会在国家会议中心召开,eoe 开发者社区创始人靳岩在 ...

    8. 《码农周刊》干货精选(Python 篇)

      <码农周刊>已经累计发送了 38 期,我们将干货内容进行了精选.此为 Python 篇. <码农周刊>往期回顾:http://weekly.manong.io/issues/ ...

    9. 一名Java架构师分享自己的从业心得,从码农到架构师我用了八年

      工作了挺久,发现有个挺有意思的现象,从程序员.高级程序员,到现在挂着架构师.专家之类的头衔,伴随着技术和能力的提高,想不明白的事情反而越来越多了. 这些疑问有些来自于跟小伙伴的交流,有些是我的自问自答 ...

    随机推荐

    1. IOS基本数据类型之枚举

      枚举是C语言中的一种基本数据类型,通过枚举可以声明一组常数,来代表不同的含义,它实际上就是一组整型常量的集合. 枚举是非常常用的一种类型,在现实生活中也很常见.比如有四个季节,在不同的季节需要显示不同 ...

    2. scala 学习笔记六 推导

      1.介绍 在Scala中,推导将生成器.过滤器.和定义组合在一起. 2.例子 有一种将result用作val(而不是var)的方式,:“就地”构建result,而不是逐项构建,利用yield关键字,当 ...

    3. Tomcat gzip果然强大,js文件压缩率50%以上

      Tomcat配置使用gzip,在server.xml中 <Connector port="9098" protocol="HTTP/1.1" connec ...

    4. ListView GridViewColumn.CellTemplate

      <ListView.View> <GridView> <GridViewColumn Header="Meaningful Use Objectives&quo ...

    5. 在CentOS/RHEL上设置SSH免密码登录

      本文会告诉你怎样在 CentOS/RHEL 上设置 SSH 免密码登录.自动登录配置好以后,你可以通过它使用 SSH (Secure Shell)和安全复制 (SCP)来移动文件. SSH 是开源的, ...

    6. [转载]C++中处理XML文件

        写Unmanaged Code在.NET时代成为一种很悲惨的事,当你需要处理XML文件时,这种感觉会变得尤其强烈.FCL中的System.XML多简单啊,连Steve Ballmer都知道怎么用. ...

    7. 【Javascript Demo】谷歌地图简单实现(附遮罩层和弹出层实现)

      虽然百度地图实现了,但只是国内的,而且前几天貌似还出问题了,对于国际的只能用谷歌地图了,所以就简单研究了下,做了个差不多的. 基本步骤,谷歌地图API文档其实写的很清楚了,先获取API密钥,然后引用j ...

    8. Sticker.js生成图片或者页面元素“速干贴”效果

      ​在线演示 本地下载 真实的效果,真的非常好玩!

    9. Hive Python Streaming的原理及写法

      在Hive中,须要实现Hive中的函数无法实现的功能时,就能够用Streaming来实现. 其原理能够理解成:用HQL语句之外的语言,如Python.Shell来实现这些功能,同一时候配合HQL语句, ...

    10. 火狐浏览器FireFox 如何将整个网页保存为图片

      使用Friefox的Pearl Cresent Page Saver插件 如图所示网页有很长的滚动条 点击右下角的该插件选项,将整个页面保存为图片 在桌面上得到了这样一个文件,大小是1263×6083 ...