通过下面这篇文章可以了解到五种IO模型和select poll和epoll的区别。
关注以下方法参数,socket调用方法结束后可以让就绪的连接的内核态数据写入到用户进程的buff中。
int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
int select(int maxfdp1,fd_set *readset,fd_set *writeset, fd_set *exceptset, const struct timeval *timeout)
第一个参数:maxfdp1最大文件描述符的个数+1 处理的时候只处理0,maxfdp1-1
第二个参数:readset 其实是一个整数数组,它是值,结果参数。一开始每个数字的每一位都是1,代表需要关闭文件描述符的编号,返回的时候代表的是该文件描述符的状态。
例如:开始传入[5,7]第一个数字表示0,31的文件描述符表示对第1个和第3个进程check (5=2^0 + 2^2),第二个7表示32,63的文件描述符表示内核需要check 32,33,34的文件描述符。如果返回结果是第一个就绪了第三个没有就绪则数组的第一个数字变为1,没有就绪的文件标识符都置为0。看到资料说select只能支持1024个文件标识符,那么应该是这里规定了数组的长度为32。
最后一个参数:timeout是设置select的超时时间。
int poll(struct pollfd *dfarray, unsigned long nfds, int timeout)
其中第一个参数是数组的起始指针,所以有人说是链表也是可以理解的。
struct pollfd {
int fd ; // 文件标示符的标志
short events; // 感兴趣的事件
short revents; //就绪的事件
}
第二个参数是文件描述符的个数,就是数组的长度可以达到2^64次方个数!
第三个参数是超时时间。
其实poll和select的操作是一样的只是支持的文件描述符的个数不一样。
至于epoll后面再分析吧。
通过下面文章我们可以了解到java NIO的基本概念,Buffer,Channel,selector
思考几个问题:
1.NIO到底解决的是什么问题,是为了避免更多的socket连接,还是为了更多的并发线程?
这个我理解是后者,因为客户端连接不可避免,客户端连接进来肯定要创建连接。但是并发的线程数则可以控制,一方面selector可以管理注册在上面的多个channel来处理数据,这样就好比一个线程可以处理多个socketChannel。
2.一个server只能有一个selector还是可以有多个selector?
我理解是多个,如果一个channel处理消息0.01s,能够接受selector的处理channel时间是1s一次轮询,那么极限就是最多100个channel注册在一个selector上面。
3.一个socketChannel和普通的一个socket连接区别是什么?
查阅资料说channel是双向的,类似于流,那是否就类似一个socket连接呢。server能够支持多少个socket连接呢。发现一个资料可以参考下,不过还是有点疑惑,希望有小伙伴可以解答下。