从零实现一个最精简的select网络服务模型

see more:http://wufazuce.com/select.html

前言

从零写一个基于select的最简单网络服务,从最基本的socket/bind/listen/accpet函数,了解每个函数每个参数代表的意义。
- 测试文件描述符fd是如何变化的;
- select事件触发的方式;
- 参考redis中select的实现;
- 读写函数read/writerecv/send有什么区别;
- listen中第二个参数backlog的作用以及表象实测;

实现select服务端

源码:https://github.com/yinnnnn/cpp_demo/blob/master/select2.c

几点实测及结论

0、文件描述符fd是如何变化的。

  • 自增的,0(标准输入),1(标准输出),2(错误输出)是保留的: https://en.wikipedia.org/wiki/File_descriptor
  • 如果中间有一个fd close了,后面的新连接会重新使用原来的fd值,所以后面接收到的client的fd不一定比前面的大。
  • 不管是打开文件的fd还是网络请求的fd都是通用的,不会混合!
  • 可以通过lsof -p 433 来查看单个进程打开的文件描述符
    lsof

1、每次select有事件触发后,再次监听必须把所有的fd重新添加到监听中,因为事件发生后fd已经被内核修改了。

FD_ZERO(&rfds);
for (int i = 0; i <= max; i++) {
    //要剔除掉已经close的
    printf("set fd=%d\n", i);
    FD_SET(i, &rfds);
}

redis中的reset操作是通过memcpy实现的。

https://github.com/antirez/redis/blob/unstable/src/ae_select.c
memcpy(&state->_rfds,&state->rfds,sizeof(fd_set));
memcpy(&state->_wfds,&state->wfds,sizeof(fd_set));

2、select有事件触发后必须遍历整个fd列表(根据FD_ISSET(i, &rfds))才能知道是哪些fd有事件触发。

3、可将bind的fd和接收到client请求的fd一起放入select中监听,不管是有新连接还是原来的client连接有读写事件都能触发select,达到真正的实时响应。

4、读写函数read/writerecv/send有什么区别,应该使用哪种

recv和send多一个参数来控制读写: http://blog.csdn.net/petershina/article/details/7946615
redis采用 read/write

5、backlog设置:未accpet的队列数

测试一:不是select响应的个数

define CONFIG_DEFAULT_TCP_BACKLOG 511

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值