做游戏行业的大神众多。我是做应用server的,小打小闹,现在到处流行大数据,分布式。都是伪的。。做应用服务器开发的大神,没听说多。做webserver的一大堆电商。。只有做游戏服务器的比较多。基本上都是从做游戏架构等方面,学习开发应用server。

skynet是云风用c和lua写的,正好准备学习lua,一起看了。研究下。

本文纯属记录。毫无技术含量,阅读需谨慎。

github下载,然后看源码,都是没文档的东西,自己慢慢琢磨。

skynet-src文件夹。

socket_poll.h文件

#ifndef socket_poll_h#define socket_poll_h#include 
typedef int poll_fd;struct event { void * s; bool read; bool write;};static bool sp_invalid(poll_fd fd);static poll_fd sp_create();static void sp_release(poll_fd fd);static int sp_add(poll_fd fd, int sock, void *ud);static void sp_del(poll_fd fd, int sock);static void sp_write(poll_fd, int sock, void *ud, bool enable);static int sp_wait(poll_fd, struct event *e, int max);static void sp_nonblocking(int sock);#ifdef __linux__#include "socket_epoll.h"#endif#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__)#include "socket_kqueue.h"#endif#endif

作为一个库,要考虑的多,这里是poll,还有kqueue和epoll,不同的系统用的不同,就得都加上。这个现在都通用,地球人都知道,不解释。

#ifndef poll_socket_epoll_h#define poll_socket_epoll_h#include 
#include
#include
#include
#include
#include
#include
#include
static boolsp_invalid(int efd) { return efd == -1;}static intsp_create() { return epoll_create(1024);}static voidsp_release(int efd) { close(efd);}static intsp_add(int efd, int sock, void *ud) { struct epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = ud; if (epoll_ctl(efd, EPOLL_CTL_ADD, sock, &ev) == -1) { return 1; } return 0;}static voidsp_del(int efd, int sock) { epoll_ctl(efd, EPOLL_CTL_DEL, sock , NULL);}static voidsp_write(int efd, int sock, void *ud, bool enable) { struct epoll_event ev; ev.events = EPOLLIN | (enable ? EPOLLOUT : 0); ev.data.ptr = ud; epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev);}static intsp_wait(int efd, struct event *e, int max) { struct epoll_event ev[max]; int n = epoll_wait(efd , ev, max, -1); int i; for (i=0;i

这个直接在h文件就实现了代码。

#ifndef poll_socket_kqueue_h#define poll_socket_kqueue_h#include 
#include
#include
#include
#include
#include
#include
#include
static boolsp_invalid(int kfd) { return kfd == -1;}static intsp_create() { return kqueue();}static voidsp_release(int kfd) { close(kfd);}static voidsp_del(int kfd, int sock) { struct kevent ke; EV_SET(&ke, sock, EVFILT_READ, EV_DELETE, 0, 0, NULL); kevent(kfd, &ke, 1, NULL, 0, NULL); EV_SET(&ke, sock, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); kevent(kfd, &ke, 1, NULL, 0, NULL);}static intsp_add(int kfd, int sock, void *ud) { struct kevent ke; EV_SET(&ke, sock, EVFILT_READ, EV_ADD, 0, 0, ud); if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { return 1; } EV_SET(&ke, sock, EVFILT_WRITE, EV_ADD, 0, 0, ud); if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { EV_SET(&ke, sock, EVFILT_READ, EV_DELETE, 0, 0, NULL); kevent(kfd, &ke, 1, NULL, 0, NULL); return 1; } EV_SET(&ke, sock, EVFILT_WRITE, EV_DISABLE, 0, 0, ud); if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { sp_del(kfd, sock); return 1; } return 0;}static voidsp_write(int kfd, int sock, void *ud, bool enable) { struct kevent ke; EV_SET(&ke, sock, EVFILT_WRITE, enable ? EV_ENABLE : EV_DISABLE, 0, 0, ud); if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1) { // todo: check error }}static intsp_wait(int kfd, struct event *e, int max) { struct kevent ev[max]; int n = kevent(kfd, NULL, 0, ev, max, NULL); int i; for (i=0;i

kqueue还没有机会用过,一直用的ubuntu系统,用的epoll,这个的写法,和select很像。

poll对应的c文件,怎么找不到。没实现。哦。原来这个poll是调用epoll和kqueue的,没有用poll event。。。

#ifndef _RWLOCK_H_#define _RWLOCK_H_struct rwlock {    int write;    int read;};static inline voidrwlock_init(struct rwlock *lock) {    lock->write = 0;    lock->read = 0;}static inline voidrwlock_rlock(struct rwlock *lock) {    for (;;) {        while(lock->write) {            __sync_synchronize();        }        __sync_add_and_fetch(&lock->read,1);        if (lock->write) {            __sync_sub_and_fetch(&lock->read,1);        } else {            break;        }    }}static inline voidrwlock_wlock(struct rwlock *lock) {    while (__sync_lock_test_and_set(&lock->write,1)) {}    while(lock->read) {        __sync_synchronize();    }}static inline voidrwlock_wunlock(struct rwlock *lock) {    __sync_lock_release(&lock->write);}static inline voidrwlock_runlock(struct rwlock *lock) {    __sync_sub_and_fetch(&lock->read,1);}#endif

__sync_synchronize。。。这是神马函数,加锁,我都没用过,这些个函数。。linux原子操作函数族。不知道boost的Atomic操作,和这个相同否。先记住,以后深入理解这个家族的函数把。

#ifndef SKYNET_ENV_H#define SKYNET_ENV_Hconst char * skynet_getenv(const char *key);void skynet_setenv(const char *key, const char *value);void skynet_env_init();#endif

这么看就是一个key-value的,就像设置配置文件一样。

#include "skynet_env.h"#include 
#include
#include
#include
struct skynet_env { int lock; lua_State *L;};static struct skynet_env *E = NULL;#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}#define UNLOCK(q) __sync_lock_release(&(q)->lock);const char *skynet_getenv(const char *key) { LOCK(E) lua_State *L = E->L; lua_getglobal(L, key); const char * result = lua_tostring(L, -1); lua_pop(L, 1); UNLOCK(E) return result;}voidskynet_setenv(const char *key, const char *value) { 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); UNLOCK(E)}voidskynet_env_init() { E = malloc(sizeof(*E)); E->lock = 0; E->L = luaL_newstate();}

终于用到lua了。。对于我这种lua小白,得好好看看。看样子,就是把key-value这个map结构放到lua中,相当于调用c++的std map了。。云风大神,看样子抛弃c++了。嘎嘎。