研究下skynet,云风大神的开源框架

转载于 http://no001.blog.51cto.com/1142339/1354154

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


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


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

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

skynet-src文件夹。

socket_poll.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef socket_poll_h
#define socket_poll_h
#include <stdbool.h>
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,不同的系统用的不同,就得都加上。这个现在都通用,地球人都知道,不解释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#ifndef poll_socket_epoll_h
#define poll_socket_epoll_h
#include <netdb.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
static  bool
sp_invalid( int  efd) {
     return  efd == -1;
}
static  int
sp_create() {
     return  epoll_create(1024);
}
static  void
sp_release( int  efd) {
     close(efd);
}
static  int
sp_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  void
sp_del( int  efd,  int  sock) {
     epoll_ctl(efd, EPOLL_CTL_DEL, sock , NULL);
}
static  void
sp_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  int
sp_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<n;i++) {
         e[i].s = ev[i].data.ptr;
         unsigned flag = ev[i].events;
         e[i].write = (flag & EPOLLOUT) != 0;
         e[i].read = (flag & EPOLLIN) != 0;
     }
     return  n;
}
static  void
sp_nonblocking( int  fd) {
     int  flag = fcntl(fd, F_GETFL, 0);
     if  ( -1 == flag ) {
         return ;
     }
     fcntl(fd, F_SETFL, flag | O_NONBLOCK);
}
#endif


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#ifndef poll_socket_kqueue_h
#define poll_socket_kqueue_h
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/event.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static  bool
sp_invalid( int  kfd) {
     return  kfd == -1;
}
static  int
sp_create() {
     return  kqueue();
}
static  void
sp_release( int  kfd) {
     close(kfd);
}
static  void
sp_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  int
sp_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  void
sp_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  int
sp_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<n;i++) {
         e[i].s = ev[i].udata;
         unsigned filter = ev[i].filter;
         e[i].write = (filter == EVFILT_WRITE);
         e[i].read = (filter == EVFILT_READ);
     }
     return  n;
}
static  void
sp_nonblocking( int  fd) {
     int  flag = fcntl(fd, F_GETFL, 0);
     if  ( -1 == flag ) {
         return ;
     }
     fcntl(fd, F_SETFL, flag | O_NONBLOCK);
}
#endif

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef _RWLOCK_H_
#define _RWLOCK_H_
struct  rwlock {
     int  write;
     int  read;
};
static  inline  void
rwlock_init( struct  rwlock *lock) {
     lock->write = 0;
     lock->read = 0;
}
static  inline  void
rwlock_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  void
rwlock_wlock( struct  rwlock *lock) {
     while  (__sync_lock_test_and_set(&lock->write,1)) {}
     while (lock->read) {
         __sync_synchronize();
     }
}
static  inline  void
rwlock_wunlock( struct  rwlock *lock) {
     __sync_lock_release(&lock->write);
}
static  inline  void
rwlock_runlock( struct  rwlock *lock) {
     __sync_sub_and_fetch(&lock->read,1);
}
#endif


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

1
2
3
4
5
6
#ifndef SKYNET_ENV_H
#define SKYNET_ENV_H
const  char  * skynet_getenv( const  char  *key);
void  skynet_setenv( const  char  *key,  const  char  *value);
void  skynet_env_init();
#endif

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# include  "skynet_env.h"
# include  <lua.h>
# include  <lauxlib.h>
# include  <stdlib.h>
# include  <assert.h>
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;
}
void
skynet_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)
}
void
skynet_env_init() {
     E = malloc(sizeof(*E));
     E->lock =  0 ;
     E->L = luaL_newstate();
}


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


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值