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开源翻译计划 一)
QQ 324186207群 enet交流技术.主要是为了研究tcp内部执行机制,欢迎大家增加探讨.小弟水平有限.翻译难免有误. . Features: ENet evolved specificall ...
- android码农神器 偷懒工具 android懒人框架 LoonAndroid 3 讲解
LoonAndroid 3.0 Loonandroid是一个注解框架,不涉及任何UI效果,目的是一个功能一个方法,以方法为最小颗粒度对功能进行拆解.把功能傻瓜化,简单化,去掉重复性的代码,隐藏复杂的实 ...
- Android码农如何一个星期转为iOS码农(不忽悠)
WeTest 导读 作为一个android客户端开发,如果你不懂点ios开发,怎么好意思说自己是客户端开发呢,本文讲解如何让android开发码农在一个星期上手IOS开发 --<记录自己IOS开 ...
- 拥抱Mac之码农篇
拥抱Mac之码农篇 使用Mac大概两年时间.之前用着公司配的一台27寸的iMac.无奈机械硬盘严重拖慢速度,影响工作心情.于是入手Macbook Retina 13.这两年的开发工作所有在Mac上完毕 ...
- 【整理】待毕业.Net码农就业求职储备
声明:本文题目来源于互联网,仅供即将从学校毕业的.Net码农(当然,我本人也是菜逼一个)学习之用.当然,学习了这些题目不一定会拿到offer,但是针对就业求职做些针对性的准备也是不错的.此外,除了技术 ...
- <开心一笑> 码农 黑客和2B程序员之间的区别
笔记本电脑 码农: 黑客: 2B程序员: 求2的32次方: 码农: System.out.println(Math.pow(2, 32)); 黑客: System.out.println(1L< ...
- [2013 eoe移动开发者大会]靳岩:从码农到极客的升级之路
(国内知名Android开发论坛 eoe开发者社区推荐:http://www.eoeandroid.com/) 前天,2013 eoe 移动开发者大会在国家会议中心召开,eoe 开发者社区创始人靳岩在 ...
- 《码农周刊》干货精选(Python 篇)
<码农周刊>已经累计发送了 38 期,我们将干货内容进行了精选.此为 Python 篇. <码农周刊>往期回顾:http://weekly.manong.io/issues/ ...
- 一名Java架构师分享自己的从业心得,从码农到架构师我用了八年
工作了挺久,发现有个挺有意思的现象,从程序员.高级程序员,到现在挂着架构师.专家之类的头衔,伴随着技术和能力的提高,想不明白的事情反而越来越多了. 这些疑问有些来自于跟小伙伴的交流,有些是我的自问自答 ...
- iOS 怎样更新APP
app更新的流程思想 得到当前版本currentVersion,将currentVersion与近期的版本latestVersion进行比較,若当前currentVersion较小.进行更新操作. 获 ...
- STL - 容器 - Array
Array是C++ 11给STL新增加的容器 ArrayTest.cpp #include <array> #include <algorithm> #include < ...
- MVC4.0网站发布
一.VS2010下MVC4.0项目的发布 首先,生成网站发布文件. 第一步,"右击"要发布的MVC4.0项目,选择"发布(B)..."选项,如图: 第二步,在& ...
- HDU 4902 Nice boat 成段线段树
操作1 的时候标记deng[rt]表示以下一段数都是与当前节点的值同样 下次操作2时直接对有deng标记的节点gcd更新 (可能还能够更简单) #include <stdio.h> #in ...
- HDUOj Ignatius and the Princess III 题目1002
母函数 组合数学 #include<stdio.h> int c1[125]; int c2[125]; int main() { int n,i,j,k; while(scanf ...
- "高可用方案工具包" high availability toolkit 1.2 公布了。version 1.2 新增了 负载均衡 load balance 的技术实现
"高可用方案工具包" high availability toolkit 1.2 公布了. version 1.2 新增了 负载均衡 load balance 的技术实现. 项目 ...
- lftp mirror 上传目录
1. lftp的确很强大, 要学习一下. sudo yum install lftp (测试了一下,ftp软件才92K,lftp有2.3M) 2. lftp mirror 能上 ...
- [Python]网络爬虫(七):Python中的正则表达式教程
转自:http://blog.csdn.net/pleasecallmewhy/article/details/8929576#t4 接下来准备用糗百做一个爬虫的小例子. 但是在这之前,先详细的整理一 ...
- Python之os.walk()
#http://www.cnblogs.com/bluescorpio/archive/2009/10/21/1587493.html os.walk() 返回结果:可以得到一个(dirpath, d ...
- 判断URL是否支持断点续传?
#python #xiaodeng #判断URL是否支持断点续传? import urllib2 req = urllib2.Request('http://ftp.ubuntu.com/') req ...