精华内容
下载资源
问答
  • skynet

    2021-01-19 15:52:55
    https://github.com/cloudwu/skynet/wiki Welcome to the skynet wiki! 欢迎使用 skynet ,这是一个轻量级的为在线游戏服务器打造的框架。...Skynet is a lightweight framework designed for online g

    https://github.com/cloudwu/skynet/wiki

    Welcome to the skynet wiki!

    欢迎使用 skynet ,这是一个轻量级的为在线游戏服务器打造的框架。但从社区 Community 的反馈结果看,它也不仅仅使用在游戏服务器领域。Uses 收集了很少一部分使用 skynet 的项目,但实际项目要多得多。欢迎你把你的项目也加到这个列表中。

    Skynet is a lightweight framework designed for online game servers. Although from the feedback of the Community , it's not limited as a game server framework. On the Uses page, it shows a few projects that have used or currently using Skynet, but there are way more projects than listed. And welcome to be the next user.

    如果你对 skynet 毫无了解,那么可以先阅读一下 GettingStarted。由于 skynet 本身并不复杂,同时建议你阅读一下源代码。参考 Blogs 会对理解设计思路和发展历史有所帮助。还有一些同学自发编写的第三方文档 ThirdPartyDocument 供参考。

    If you are new to Skynet, the best way to start is GettingStarted. And because the implementation of Skynet is not complicated, I would recommend you read source code as well. There are reference Blogs helping you understand the thoughts, design and version changes. There is also an unofficial doc ThirdPartyDocument .

    Build skynet 非常简单,动手编译一个试着玩一下是个很好的开始。examples 和 test 目录下有些例子。如果你想自己动手做二次开发,你可以从理解 Bootstrap 开始,一开始不要尝试集群 Cluster

    To Build Skynet is very simple, you can try it from downloading one and compiling it. Some examples can be found in examples and test directories. If you'd like to customize Skynet based on your own project, it's better to start from understanding Bootstrap , I would not recommend beginning with Cluster .

    虽然 skynet 的核心是由 C 语言编写,但如果只是简单使用 skynet ,并不要求 C 语言基础。但你需要理解 Actor 模式的工作方式,把你的业务拆分成多个服务来协同工作。Lua 是必要的开发语言,你只需要懂得 Lua 就可以使用 LuaAPI 来完成服务间的通讯协作。另外,Snax 可能会是更简单的方式。关于服务间共享数据,除了用消息传递的方式外,还可以参考 ShareData 。skynet 已提供的功能可以参考 APIList

    Although the core of Skynet is developed in c, you are not required to know c if you just want to use the functionalities of Skynet. What you need is to understand how Actor mode works, which breaks up your project into services and they collaborate with each other. Lua is required to develop Skynet applications, you'll need to learn how to use LuaAPI to manage the collaboration of services. In addition, Snax is an even simpler solution. Regarding the data sharing between services, besides using message queue, you can also take a look at ShareData. Skynet has offered a bunch of functionalities that can be found in APIList.

    当然只有这些仅仅可以让 skynet 内部的服务相互协作。要做到给客户端提供服务,还需要使用 Socket API ,或者使用已经编写好的 GateServer 模板解决大量客户端接入的问题。或许你还需要为 C/S 通讯制订一套通讯协议,skynet 并没有规定这个协议,可以自由选择。当然你也可以看看 Sproto

    With the above modules I mentioned, skynet can make internal services work. To provide services to the client, you'll need to use Socket API or use GateServer to resolve high concurrent users' problems. Maybe you can make your own C/S protocol, Skynet doesn't force a specific protocol, you can come up with your own design. An example can be found at Sproto.

    通过这套 Socket API以及更方便的 SocketChannel(更容易实现 socket 池和断开重连) ,可以让 skynet 异步调度外部 socket 事件。对外部独立服务的访问,最好都通过这套 API 的封装。如果外部库直接调用系统的 socket ,很可能阻塞住 skynet 的工作线程,发挥不出性能。访问诸如数据库等 ExternalService,最好可以做一次封装。

    With Socket API and SocketChannel , which makes it easier to implement socket pool and reconnect, you can use Skynet to call socket even asynchronously. It's best to use this API for external independent services. If using external lib to call system socket, it's very possible to be blocked on the worker threads of Skynet and couldn't make best use of Skynet. If you'd like to access ExternalService like databases, you'd better implement it by yourself.

    如果你找不到你需要的外部组件的 skynet driver ,可以自己来编写,社区欢迎你的贡献。当然,你也可以写一个独立程序和外部组件沟通,再和 skynet 通讯。通讯协议可以自行定义,也可以使用 Http 协议。也可以使用 WebSocket。

    If you could not find the external components you need, you can develop your own extension and you are always welcome to contribute. You can also develop your own application as a middle layer to communicate with external components and talk to Skynet. Feel free to choose your own protocol, Http or WebSocket.

    展开全文
  • Skynet

    2014-10-14 10:39:05
    云风的开源并发框架Skynet第一个正式版发布 文章由刘江总编于2014-04-23 23:33分享 评论(2) 并发开源云风Skynet并发框架消息队列Actor模型 云风在博客里宣布发布Skynet的第一个正式版,不过版本号...
    • 本文 源自:http://geek.csdn.net/news/detail/7364

    云风在博客里宣布发布Skynet的第一个正式版,不过版本号却是0.1.0。

    项目的Github地址是https://github.com/cloudwu/skynet

    Skynet是云风2012年7月为简悦科技的游戏开发的服务器底层框架,本质上是一个消息队列。原来的框架是用Erlang实现的,但性能有问题,所以云风用不到3000行C语言核心代码重写了。采用了单进程多线程的模型。核心功能是消息分发、Actor调度和Timer管理。8月1日开源

    更多技术细节可以参考:

    展开全文
  • skynet-源码

    2021-03-15 22:30:53
    skynet
  • skynet 入门

    2018-12-03 10:42:04
    skynet 学习 skynet 入门资料 微服务器开发框架 C/lua
  • skynet客户端

    2016-10-23 18:41:12
    skynet客户端
  • Skynet is a lightweight online game framework which can be used in many other fields. Build For Linux, install autoconf first for jemalloc: git clone https://github.com/cloudwu/skynet.git cd skynet ...
  • Skynet手册

    2018-06-18 00:57:45
    云风的游戏服务器框架 Skynet手册,Skynet是用lua写的一个高效游戏服务器框架
  • skynet mmorpg

    2017-01-04 10:52:39
    skynet mmorpg 游戏开发案例代码,可用于 skynet 的游戏框架研究
  • skynet.pack与skynet.unpack实现分析 skynet.lua 358行 可以看到如下定义 skynet.pack = assert(c.pack) skynet.packstring = assert(c.packstring) skynet.unpack = assert(c.unpack) skynet.tostring = assert(c....

    skynet.pack与skynet.unpack实现分析

    skynet.lua
    358行 可以看到如下定义

    skynet.pack = assert(c.pack)
    skynet.packstring = assert(c.packstring)
    skynet.unpack = assert(c.unpack)
    skynet.tostring = assert(c.tostring)
    skynet.trash = assert(c.trash)
    
    local c = require "skynet.core"
    

    可以知道这是c实现的 找到文件 lua-skynet.c

    LUAMOD_API int
    luaopen_skynet_core(lua_State *L) {
    	luaL_checkversion(L);
    
    	luaL_Reg l[] = {
    		{ "send" , lsend },
    		{ "genid", lgenid },
    		{ "redirect", lredirect },
    		{ "command" , lcommand },
    		{ "intcommand", lintcommand },
    		{ "addresscommand", laddresscommand },
    		{ "error", lerror },
    		{ "harbor", lharbor },
    		{ "callback", lcallback },
    		{ "trace", ltrace },
    		{ NULL, NULL },
    	};
    
    	// functions without skynet_context
    	luaL_Reg l2[] = {
    		{ "tostring", ltostring },
    		{ "pack", luaseri_pack },
    		{ "unpack", luaseri_unpack },
    		{ "packstring", lpackstring },
    		{ "trash" , ltrash },
    		{ "now", lnow },
    		{ "hpc", lhpc },	// getHPCounter
    		{ NULL, NULL },
    	};
    
    	lua_createtable(L, 0, sizeof(l)/sizeof(l[0]) + sizeof(l2)/sizeof(l2[0]) -2);
    
    	lua_getfield(L, LUA_REGISTRYINDEX, "skynet_context");
    	struct skynet_context *ctx = lua_touserdata(L,-1);
    	if (ctx == NULL) {
    		return luaL_error(L, "Init skynet context first");
    	}
    
    
    	luaL_setfuncs(L,l,1);
    
    	luaL_setfuncs(L,l2,0);
    
    	return 1;
    }
    

    可以看到pack、unpack都在这里
    luaseri_pack 的实现在 lua-seri.lua文件中

    //一个链表
    struct block {
    	struct block * next;
    	char buffer[BLOCK_SIZE];
    };
    
    struct write_block {
    	struct block * head;
    	struct block * current;
    	int len;
    	int ptr;
    };
    
    LUAMOD_API int
    luaseri_pack(lua_State *L) {
    	struct block temp;
    	temp.next = NULL;
    	struct write_block wb;
    	wb_init(&wb, &temp);
    	pack_from(L,&wb,0);
    	assert(wb.head == &temp);
    	seri(L, &temp, wb.len);
    
    	wb_free(&wb);
    
    	return 2;
    }
    
    //做一些初始化的工作
    static void
    wb_init(struct write_block *wb , struct block *b) {
    	wb->head = b;
    	assert(b->next == NULL);
    	wb->len = 0;
    	wb->current = wb->head;
    	wb->ptr = 0;
    }
    
    //打包数据
    static void
    pack_from(lua_State *L, struct write_block *b, int from) {
    	//lua_gettop(L) 获取栈的大小
    	int n = lua_gettop(L) - from; //n 为整个栈的大小
    	int i;
    	for (i=1;i<=n;i++) {
    		pack_one(L, b , from + i, 0);
    	}
    }
    
    //一个一个打包
    //#define MAX_DEPTH 32
    static void
    pack_one(lua_State *L, struct write_block *b, int index, int depth) {
    	if (depth > MAX_DEPTH) { //depth在这里始终为0
    		wb_free(b);
    		luaL_error(L, "serialize can't pack too depth table");
    	}
    	int type = lua_type(L,index); //获取数据类型
    	switch(type) {
    	case LUA_TNIL:
    		wb_nil(b);
    		break;
    	case LUA_TNUMBER: {
    		if (lua_isinteger(L, index)) { //int类型
    			lua_Integer x = lua_tointeger(L,index);
    			wb_integer(b, x);
    		} else {
    			lua_Number n = lua_tonumber(L,index);
    			wb_real(b,n);
    		}
    		break;
    	}
    	case LUA_TBOOLEAN: 
    		wb_boolean(b, lua_toboolean(L,index));
    		break;
    	case LUA_TSTRING: {
    		size_t sz = 0;
    		const char *str = lua_tolstring(L,index,&sz);
    		wb_string(b, str, (int)sz);
    		break;
    	}
    	case LUA_TLIGHTUSERDATA:
    		wb_pointer(b, lua_touserdata(L,index));
    		break;
    	case LUA_TTABLE: {
    		if (index < 0) {
    			index = lua_gettop(L) + index + 1;
    		}
    		wb_table(L, b, index, depth+1);
    		break;
    	}
    	default:
    		wb_free(b);
    		luaL_error(L, "Unsupport type %s to serialize", lua_typename(L, type));
    	}
    }
    
    #define TYPE_NIL 0
    #define TYPE_BOOLEAN 1
    // hibits 0 false 1 true
    #define TYPE_NUMBER 2
    // hibits 0 : 0 , 1: byte, 2:word, 4: dword, 6: qword, 8 : double
    #define TYPE_NUMBER_ZERO 0
    #define TYPE_NUMBER_BYTE 1
    #define TYPE_NUMBER_WORD 2
    #define TYPE_NUMBER_DWORD 4
    #define TYPE_NUMBER_QWORD 6
    #define TYPE_NUMBER_REAL 8
    
    #define TYPE_USERDATA 3
    #define TYPE_SHORT_STRING 4
    // hibits 0~31 : len
    #define TYPE_LONG_STRING 5
    #define TYPE_TABLE 6
    
    #define COMBINE_TYPE(t,v) ((t) | (v) << 3)   //用一个字节表示类型和长度
    
    #define BLOCK_SIZE 128
    #define MAX_DEPTH 32
    
    static inline void
    wb_integer(struct write_block *wb, lua_Integer v) {
    	int type = TYPE_NUMBER;
    	if (v == 0) {
    		uint8_t n = COMBINE_TYPE(type , TYPE_NUMBER_ZERO); //  (10) | (0000) = 00000010
    		wb_push(wb, &n, 1); //占用一个字节
    	} else if (v != (int32_t)v) {
    		uint8_t n = COMBINE_TYPE(type , TYPE_NUMBER_QWORD);  // (10) | (110000) = 00110010 
    		int64_t v64 = v;
    		wb_push(wb, &n, 1);
    		wb_push(wb, &v64, sizeof(v64)); //占用九个字节
    	} else if (v < 0) {
    		int32_t v32 = (int32_t)v;
    		uint8_t n = COMBINE_TYPE(type , TYPE_NUMBER_DWORD);
    		wb_push(wb, &n, 1);
    		wb_push(wb, &v32, sizeof(v32)); //占用5个字节
    	} else if (v<0x100) {
    		uint8_t n = COMBINE_TYPE(type , TYPE_NUMBER_BYTE);
    		wb_push(wb, &n, 1);
    		uint8_t byte = (uint8_t)v;
    		wb_push(wb, &byte, sizeof(byte));
    	} else if (v<0x10000) {
    		uint8_t n = COMBINE_TYPE(type , TYPE_NUMBER_WORD);
    		wb_push(wb, &n, 1);
    		uint16_t word = (uint16_t)v;
    		wb_push(wb, &word, sizeof(word));
    	} else {
    		uint8_t n = COMBINE_TYPE(type , TYPE_NUMBER_DWORD);
    		wb_push(wb, &n, 1);
    		uint32_t v32 = (uint32_t)v;
    		wb_push(wb, &v32, sizeof(v32));
    	}
    }
    

    unpack

    //解包
    int
    luaseri_unpack(lua_State *L) {
    	if (lua_isnoneornil(L,1)) {
    		return 0;
    	}
    	void * buffer;
    	int len;
    	if (lua_type(L,1) == LUA_TSTRING) {
    		size_t sz;
    		 buffer = (void *)lua_tolstring(L,1,&sz);
    		len = (int)sz;
    	} else {
    		buffer = lua_touserdata(L,1);
    		len = luaL_checkinteger(L,2);
    	}
    	if (len == 0) {
    		return 0;
    	}
    	if (buffer == NULL) {
    		return luaL_error(L, "deserialize null pointer");
    	}
    
    	lua_settop(L,1);
    	struct read_block rb;
    	rball_init(&rb, buffer, len);
    
    	int i;
    	for (i=0;;i++) {
    		if (i%8==7) {
    			luaL_checkstack(L,LUA_MINSTACK,NULL);
    		}
    		uint8_t type = 0;
    		uint8_t *t = rb_read(&rb, sizeof(type));
    		if (t==NULL)
    			break;
    		type = *t;
    		push_value(L, &rb, type & 0x7, type>>3); 
    	}
    
    	// Need not free buffer
    
    	return lua_gettop(L) - 1;
    }
    
    //先读取一个字节  获取类型与大小
    static void *
    rb_read(struct read_block *rb, int sz) {
    	if (rb->len < sz) {
    		return NULL;
    	}
    
    	int ptr = rb->ptr;
    	rb->ptr += sz;
    	rb->len -= sz;
    	return rb->buffer + ptr;
    }
    

    //TYPE_NUMBER_ZERO 00000010 type & 0x7 = 10 = 2 type>>3 = 0

    static void
    push_value(lua_State *L, struct read_block *rb, int type, int cookie) {
    	switch(type) {
    	case TYPE_NIL:
    		lua_pushnil(L);
    		break;
    	case TYPE_BOOLEAN:
    		lua_pushboolean(L,cookie);
    		break;
    	case TYPE_NUMBER:
    		if (cookie == TYPE_NUMBER_REAL) {
    			lua_pushnumber(L,get_real(L,rb));
    		} else {
    			lua_pushinteger(L, get_integer(L, rb, cookie));
    		}
    		break;
    	case TYPE_USERDATA:
    		lua_pushlightuserdata(L,get_pointer(L,rb));
    		break;
    	case TYPE_SHORT_STRING:
    		get_buffer(L,rb,cookie);
    		break;
    	case TYPE_LONG_STRING: {
    		if (cookie == 2) {
    			uint16_t *plen = rb_read(rb, 2);
    			if (plen == NULL) {
    				invalid_stream(L,rb);
    			}
    			uint16_t n;
    			memcpy(&n, plen, sizeof(n));
    			get_buffer(L,rb,n);
    		} else {
    			if (cookie != 4) {
    				invalid_stream(L,rb);
    			}
    			uint32_t *plen = rb_read(rb, 4);
    			if (plen == NULL) {
    				invalid_stream(L,rb);
    			}
    			uint32_t n;
    			memcpy(&n, plen, sizeof(n));
    			get_buffer(L,rb,n);
    		}
    		break;
    	}
    	case TYPE_TABLE: {
    		unpack_table(L,rb,cookie);
    		break;
    	}
    	default: {
    		invalid_stream(L,rb);
    		break;
    	}
    	}
    }
    
    展开全文
  • skynet中服务器启动需要使用config配置,这其中设计到了环境变量的设置 和 环境变量的值的获取 skynet.setenv 和 skynet.send 源码 在skynet.lua 中的代码 function skynet.getenv(key) return (c.command("GETENV...

    skynet中服务器启动需要使用config配置,这其中设计到了环境变量的设置 和 环境变量的值的获取

    skynet.setenv 和 skynet.send 源码

    在skynet.lua 中的代码
    
    function skynet.getenv(key)
    	return (c.command("GETENV",key))
    end
    
    function skynet.setenv(key, value)
    	assert(c.command("GETENV",key) == nil, "Can't setenv exist key : " .. key)
    	c.command("SETENV",key .. " " ..value)
    end
    

    从lua代码看,函数接口实际是调用的 c.command 接口, 查看 skynet.lua 文件头定义:

    local c = require "skynet.core"
    

    接口来源于 skynet.core 模块中,代码路径: lualib-src/lua-skynet.c

    lcommand

    static int
    lcommand(lua_State *L) {
    	struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
    	const char * cmd = luaL_checkstring(L,1);
    	const char * result;
    	const char * parm = NULL;
    	if (lua_gettop(L) == 2) {
    		parm = luaL_checkstring(L,2);
    	}
    
    	result = skynet_command(context, cmd, parm);
    	if (result) {
    		lua_pushstring(L, result);
    		return 1;
    	}
    	return 0;
    }
    

    接下来内容主要是分析 lcommand 函数的调用过程。(以 skynet.setenv 为例子)

    1. 先从lua栈中获取了传入的参数并赋值
    - cmd = ’GETENV‘
    - parm = '我们需要查询的key'
    
    1. 调用 skynet_command 接口

    skynet_command

    static struct command_func cmd_funcs[] = {
    	{ "TIMEOUT", cmd_timeout },
    	{ "REG", cmd_reg },
    	{ "QUERY", cmd_query },
    	{ "NAME", cmd_name },
    	{ "EXIT", cmd_exit },
    	{ "KILL", cmd_kill },
    	{ "LAUNCH", cmd_launch },
    	{ "GETENV", cmd_getenv },
    	{ "SETENV", cmd_setenv },
    	{ "STARTTIME", cmd_starttime },
    	{ "ABORT", cmd_abort },
    	{ "MONITOR", cmd_monitor },
    	{ "STAT", cmd_stat },
    	{ "LOGON", cmd_logon },
    	{ "LOGOFF", cmd_logoff },
    	{ "SIGNAL", cmd_signal },
    	{ NULL, NULL },
    };
    
    const char *
    skynet_command(struct skynet_context * context, const char * cmd , const char * param) {
    	struct command_func * method = &cmd_funcs[0];
    	while(method->name) {
    		if (strcmp(cmd, method->name) == 0) {
    			return method->func(context, param);
    		}
    		++method;
    	}
    
    	return NULL;
    }
    

    在代码中能看到 { “GETENV”, cmd_getenv }, { “SETENV”, cmd_setenv },就是本文讨论的 skynet.getenv 和 skynet.setenv 的底层接口了。
    在 skynet_command 函数中,循环查找我们需要执行的命令。找到命令后就调用定义好的函数接口 cmd_getenv 或则 cmd_setenv。

    cmd_getenv 和 cmd_setenv

    代码路径:skynet-src/skynet_env.c

    #include "skynet.h"
    #include "skynet_env.h"
    #include "spinlock.h"
    
    #include <lua.h>
    #include <lauxlib.h>
    
    #include <stdlib.h>
    #include <assert.h>
    
    struct skynet_env {
    	struct spinlock lock;
    	lua_State *L;
    };
    
    static struct skynet_env *E = NULL;
    
    const char * 
    skynet_getenv(const char *key) {
    	SPIN_LOCK(E)
    
    	lua_State *L = E->L;
    	
    	lua_getglobal(L, key);
    	const char * result = lua_tostring(L, -1);
    	lua_pop(L, 1);
    
    	SPIN_UNLOCK(E)
    
    	return result;
    }
    
    void 
    skynet_setenv(const char *key, const char *value) {
    	SPIN_LOCK(E)
    	
    	lua_State *L = E->L;
    	lua_getglobal(L, key);
    	assert(lua_isnil(L, -1));
    	lua_pop(L,1);
    	lua_pushstring(L,value);
    	lua_setglobal(L,key);
    
    	SPIN_UNLOCK(E)
    }
    
    void
    skynet_env_init() {
    	E = skynet_malloc(sizeof(*E));
    	SPIN_INIT(E)
    	E->L = luaL_newstate();
    }
    

    这里面代码就比较简单了,就是在lua虚拟机里面设置 和 获取变量。
    但这里需要注意的是:

    struct skynet_env {
        struct spinlock lock;
        lua_State *L;
    };
    

    skynet中,环境变量是单独使用一个虚拟机保存的环境变量数据。

    展开全文
  • skynetskynet.response

    2020-04-29 08:26:52
    在前面的文章:skynet:session 中,已经使用过 skynet.ret / skynet.retpack 对消息进行应答。但这两个函数有一个使用限制,即:消息接收与消息应答必须在同一个协程里完成,也就是说:请求被哪一个协程接收,就...
  • skynet 源码赏析

    2019-04-28 18:00:47
    skynet的源码赏析
  • 注意:该文章暂且只分析skynet框架的lua层,底层待后续分析 首先知道 启动一个服务 必须调用 skynet.start函数 且服务间的调度必须通过消息的形式才能驱动 现在的代码都可在skynet.lua 中可以找到 //源码如下 function...
  • skynet初探

    2020-10-20 12:01:32
    local skynet = require "skynet" skynet.start(function() print("Sever start") skynet.newservice("simpledb") --发消息给simpledb服务 skynet.send("SIMPLEDB","lua","TEST") local i = 0 while true do ...
  • skynet源码赏析

    2018-09-19 17:31:07
    skynet源代码详细解析,让你快速了解SKYNET的全貌。
  • local skynet = require("skynet") function task1( ) skynet.error("start wait") --1 因为1先fork skynet.wait() --挂起 skynet.error("end wait") --4 end function task2( co ) skynet.error("s...
  • Skynet入门

    千次阅读 2019-07-02 22:41:06
    文章目录前导Skynet 核心解决什么问题Skynet 核心不解决什么问题Skynet 做什么服务间高效的通讯通信消息格式session 和 typeSkynet 的消息调度 前导 本人在Skynet开源初期就持续关注,阅读了Skynet的大部份代码,...
  • skynet.send(addr,type,...) //addr 可以是服务句柄也可以是别名 type消息类型 ... 参数 非阻塞 不需要应答 skynet.call(addr,type,...) //阻塞 需要应答 skynet.ret(msg,sz) //回应消息 首先上示例代码 ...
  • skynet queue

    2021-03-18 00:40:38
    由于skynet服务有重入问题,所以找到了一个skynet queue方法。 简单用法,假设test为在服务中需要顺序执行的函数。只要把一个函数往queue扔就行了。 local function test() print("hello world") end local ...
  • Skynet Error

    2020-12-25 18:35:53
    at Skynet.SkynetAgent.Tick () [0x00000] in :0 at RimWorld.Planet.WorldPawns.WorldPawnsTick () [0x00000] in :0 at RimWorld.Planet.World.WorldTick () [0x00000] in :0 at Verse.TickManager....
  • #ifndef SKYNET_MODULE_H #define SKYNET_MODULE_H struct skynet_context; typedef void * (*skynet_dl_create)(void); typedef int (*skynet_dl_init)(void * inst, struct skynet_context *, const char * par....
  • Skynet模块

    2019-02-19 03:03:57
    Skynet模块 Actor在Skynet中被称为模块,每个模块都是由用户逻辑和内部框架逻辑组成。用户逻辑相当于模块的皮囊,在框架中使用skynet-module对象表示,实现在skynet-src/skynet_module.c中,代表一个动态库。Skynet...
  • skynet初学

    2019-10-04 15:43:24
    记录下命令 git clone https://github.com/cloudwu/skynet.git sudo apt-get install autoconf sudo apt-get install libreadline-dev ...发现个不错的skynet研究网站http://forthxu.com/blog/skynet.h...
  • skynet-mingw, 对skynet无任何改动的windows版
  • local skynet = require("skynet") function task( ) skynet.error("start sleep:",coroutine.running()) --被唤醒 然后sleep 5s skynet.sleep(500) skynet.error("end sleep:",coroutine.running()) e...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,526
精华内容 1,410
热门标签
关键字:

skynet