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架构师分享自己的从业心得,从码农到架构师我用了八年
工作了挺久,发现有个挺有意思的现象,从程序员.高级程序员,到现在挂着架构师.专家之类的头衔,伴随着技术和能力的提高,想不明白的事情反而越来越多了. 这些疑问有些来自于跟小伙伴的交流,有些是我的自问自答 ...
- .NET反射 Type类
不知道大家有过这样类似的编码 ? 1 Type type=typeof(T);//T是传入的类型 这样写已经是在潜意思的使用反射了.不管你是否知道,但是这是事实. Type是一个抽象类,必须进行实例化 ...
- Java基础(十一):接口
一.接口: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 接口并不是 ...
- 解决 WIn7 启动时“你有等待写入光盘的文件”
这几天启动时Win7总是要提示“您有等待写入光盘的文件”,启动时间也变慢. 可能是前几日通过资源管理器刻录光盘的时候留下的垃圾. 在C:\Users\ibm\AppData\Local\Microso ...
- 【架构】SpringCloud JHipster -微服务相关资料
SpringCloud-微服务相关资料 基于Spring Boot和Spring Cloud实现微服务架构学习(四)-Spring Cloud总结 - zeb_perfect的专栏 - 博客频道 - ...
- php中120个内置函数
php中实现事件模式 https://yq.aliyun.com/ziliao/162660 <?php class Event{ private $events = []; public fu ...
- 算法笔记_209:第六届蓝桥杯软件类决赛部分真题(Java语言B组)
目录 1 分机号 2 五星填数 3 表格计算 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 分机号 标题:分机号 X老板脾气古怪,他们公司的电话分机号都是3位数,老板规定,所有号码必须是降序排列, ...
- MongoDB和关系型数据库简单对比
MongoDB 是一个跨平台的,面向文档的数据库,提供高性能,高可用性和可扩展性方便. MongoDB 工作在收集和文件的概念. 数据库:数据库是一个物理容器集合.每个数据库都有自己的一套文件系统上的 ...
- java 将字符串数组变为字典顺序排序后的字符串数组
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class String ...
- python之函数用法bin()
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法bin() #bin() #说明:一个整数转换为一个二进制字符串 ''' bin(.. ...
- newInstance() 的参数版本与无参数版本
通过反射创建新的类示例,有两种方式: Class.newInstance() Constructor.newInstance() 以下对两种调用方式给以比较说明: Class.newInstance ...