恋恋风辰的个人博客


  • Home

  • Archives

  • Categories

  • Tags

  • Search

简单循环服务器

Posted on 2017-08-07 | In 网络编程

客户端部分:

比较简单

创建socket 然后connect服务器,进行通讯
https://cdn.llfc.club/easyloopser1.png

Read more »

简单的并发服务器(多个线程各自accept)

Posted on 2017-08-07 | In 网络编程

基于之前讲述的简单循环服务器,做一个多个线程各自accept的服务器demo由于多个线程各自accept,容易造成数据错误,需要在accept前后枷锁
先看下客户端
客户端创建socket,初始化服务器地址信息,然后进行连接
https://cdn.llfc.club/easymulser1.png

Read more »

对于redis框架的理解(三)

Posted on 2017-08-07 | In 网络编程

上一篇讲完了initServer的大体流程,其中aeCreateEventLoop(),这个函数没有详细说明,我们在这一篇里讲述Ae.h和Ae.c, 这里面的api阐述了如何创建

eventLoop和添加文件读写事件等等。

ae.h中的解释

//文件读写事件回调函数
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);

//定时器回调函数
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
//事件结束回调函数,析构一些资源
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
//不是很清楚,应该是进程结束前做的回调函数
typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);

Read more »

对于redis框架的理解(二)

Posted on 2017-08-07 | In 网络编程

之前梳理过redis main函数主体流程

`大体是 initServerConfig() -> loadServerConfig()

-> daemonize() -> initServer() -> aeSetBeforeSleepProc()

->aeMain() -> aeDeleteEventLoop();

initServerConfig() 初始化server的配置

loadServerConfig()会从配置文件里加载对应的配置

daemonize()创建守护进程

看一下daemonize的函数组成

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
void daemonize(void) {
  int fd;

  if (fork() != 0) exit(0); /* parent exits */
  //设置为首进程
  //之前parent和child运行在同一个session里,

  //parent是会话(session)的领头进程,
  //parent进程作为会话的领头进程,如果exit结束执行的话,

  //那么子进程会成为孤儿进程,并被init收养。
  //执行setsid()之后,child将重新获得一个新的会话(session)id。
  setsid(); /* create a new session */

  /* Every output goes to /dev/null. If Redis is daemonized but
  * the 'logfile' is set to 'stdout' in the configuration file
  * it will not log at all. */

  // /dev/null相当于黑洞文件,所有写入他的数据都会消失,

  //从他里面读不出数据
  if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
    dup2(fd, STDIN_FILENO); //将标准输入重定向到fd
    dup2(fd, STDOUT_FILENO); //将标准输出重定向到fd
    dup2(fd, STDERR_FILENO); //将错误输出重定向到fd
    if (fd > STDERR_FILENO)

      close(fd);

   }
}
Read more »

对于redis框架的理解(四)

Posted on 2017-08-07 | In 网络编程

上一篇讲述了eventloop的结构和创建,添加文件事件删除文件事件,派发等等。

而eventloop主要就是调用不同网络模型完成事件监听和派发的。

这一篇主要讲述epoll网络模型,redis是如何封装和调用的

下面是epoll_event的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
epoll_event 结构

struct epoll_event
{
uint32_t events; //epoll_event 要注册的事件类型
epoll_data_t data; //User data //联合体用于存储用户要保存的数据
}

typedef union epoll_data
{
void * ptr;
uint32_t u32;
uint64_t u64;
int fd; //一般存储accept后生成的socketfd

}epoll_data_t

*/
Read more »

libiop网络库数据结构和基础知识

Posted on 2017-08-07 | In 网络编程

最近朋友推荐,学习了libiop这个网络库,作者封装的很全面,代码很简洁

适合初学者学习基于事件驱动的网络io,先看看iop_def.h, 这里面定义了常用的数据结构

tag_iop_base_t 主要用于管理所有事件,每个事件是一个iop_t,

maxio表示最大的文件描述符,

free_list_head 表示可用的空闲列表头部id,一般用iops + free_list_head取出iop_t 的元素

同理free_list_tail,最后一个可用iop,

iop_op_t 是封装了几个函数指针的结构体,

包括网络模型的名字,事件的添加,事件的删除,事件的更改,事件的派发

Read more »

libiop通讯流程和api讲解

Posted on 2017-08-07 | In 网络编程

上一篇讲到了libiop基本结构,这次根据libiop提供的test跟踪下消息和运行流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void echo_server_test()
{
int keepalive_timeout = 60;
iop_base_t *base = iop_base_new(10240);
printf("create a new iop_base_t object.\n");
iop_add_tcp_server(base,"0.0.0.0",7777,
my_echo_parser,my_echo_processor,
my_echo_on_connect,my_echo_on_destroy,my_echo_on_error,
keepalive_timeout);
printf("create a new tcp server on port 7777.\n");
printf("start iop run loop.\n");
iop_run(base);

}

echo_server_test 函数内部添加了一个tcpserver,将函数一层一层展开,展开iop_add_tcp_server

Read more »

select网络模型知识总结

Posted on 2017-08-07 | In 网络编程

select模型支持IO多路复用,select函数如下

1
2
3
4
5
6
int select (
IN int nfds, //windows下无意义,linux有意义
IN OUT fd_set* readfds, //检查可读性
IN OUT fd_set* writefds, //检查可写性
IN OUT fd_set* exceptfds, //例外数据
IN const struct timeval* timeout); //函数的返回时间

逐个解释每个参数意义:

nfds:一个整型变量,表示比最大文件描述符+1

readfds: 这个集合监测读事件的描述符,将要监听读事件的文件描述符放入readfds中,通过调用select,readfds中将没有就绪的读事件文件描述符清除,留下

就绪的读事件描述符,可以通过read或者recv来处理

writefds:这个集合监测写事件的描述符,将要监听的写事件的文件描述符放入writefds中,通过调用select,writefds中没有就绪的写事件文件描述符被清除,留下

就绪的写事件描述符,可以通过write或者send来处理。

Read more »

对于redis底层框架的理解(五)

Posted on 2017-08-07 | In 网络编程

之前总结了redis的通讯流程,基本框架,epoll的封装等等,这次介绍下redis对于select模型的封装

1
2
3
4
5
6
7
8
9
//select 模型
typedef struct aeApiState {
//读文件描述符集合,写文件描述符集合
fd_set rfds, wfds;
/* We need to have a copy of the fd sets as it's not safe to reuse
* FD sets after select(). */
//读写集合的副本
fd_set _rfds, _wfds;
} aeApiState;

_rfds和_wfds是读写结合的副本,因为select调用后会将读写集合中未就绪的文件描述符清除,所以每次用_rfds和_wfds传入,就不用担心原读写集合描述符被清除。

Read more »

epoll的一些细节和注意事项

Posted on 2017-08-07 | In 网络编程

epoll_event结构

1
2
3
4
5
6
7
8
9
10
11
12
13
struct epoll_event
{
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
} __attribute__ ((__packed__));

typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;

epoll_data是一个联合体,有的网络库使用了fd字段,比如redis,有的使用了u32,比如libiop,个人认为在epoll_wait之后内核会自动移动
epoll_event队列的内容。因为epoll_wait返回就绪的文件描述符数量,之后我们采用循环从0到n,从epoll_event队列中取出对应第i个 epoll_event结构,通过epoll_data中的fd或者u32回调找到用户自己封装的事件回调单元,调用对应的回调函数。

Read more »
<1…333435…37>

370 posts
17 categories
21 tags
RSS
GitHub ZhiHu
© 2025 恋恋风辰 本站总访问量次 | 本站访客数人
Powered by Hexo
|
Theme — NexT.Muse v5.1.3