man 2 socket #非阻塞的真实含义是没有连接时accept返回-1(Java里返回Null,C语言返回-1),没有数据时read返回0.
SOCK_NONBLOCK Set the O_NONBLOCK file status flag on the new open file description. Using this
flag saves extra calls to fcntl(2) to achieve the same result. #fcntl设置也成。
java里设置:ss.configureBlocking(false); #重点 OS NOBLOCK。
C里:
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(listenfd, F_SETFL, O_NONBLOCK); // 设置非阻塞方式
for(i=0; i<wait_fds; ++i ) // for循环中以进程处理epoll事件,更稳定。
{
if( events[i].data.fd == listenfd ){
connfd = accept( listenfd, (struct sockaddr *)&clientaddr, &clilen );
printf("accept return listenfd=%d\n",connfd);
if( connfd < 0 ){
perror("connfd < 0");
exit(1);
}
// 设置非阻塞
if (fcntl( connfd, F_SETFL, fcntl( connfd, F_GETFD, 0)|O_NONBLOCK) == -1){
continue;
}
accept、read、write: -1 不会阻塞。默认recv(5...阻塞。NIO在Java里指:
1)Java New:文件和楼socket都封装成新的东西,可以select统一侦听状态。
2)Unix NOBLOCKING。
BLOCKING的缺点弊端:每客户端、每线程【阻塞】。
man 2 accept #此调用在发生错误时返回-1.若成功则返回一个非负整数标识这个 连接套接字. NOBLOCKING -1
man 2 read #生错误时返回-1,并置 errno 为相应值.在这种情况下无法得知文件偏移位置是否有变化.在读取了一定量的数据后被信号所中断,并返回 -1(且 errno 被设置为EINTR),或者返回已读取的数据量.
1万个连接 1个人发来数据:
accept返回都是-1,来了数据读了一部分后,你又回去处理连接了,数据读不全。于是出现粘包。
但是你在一个循环里,全量遍历O(n)系统调用。
man 2 select:
多少条路、有多少个读的、多少个写的。
select(3,5) # 3有没有连接,5有没有连接。
selec(t3,5,6,7,8,9,10,11) O(1)只需要调一次即可。
accept (3) = 6
recv(5) O(m) #多路复用只能给你返回状态,程序需要自己调用R/W你的IO ,只要自己去读去取就叫同步模型。Netty里全是同步IO模型:无论是在当前线程还是其它线程NIO BIO New IO(指文件、socket一块给弄成一个NewIO),N:还有一个是Noblocking,也就是没来连接时返回-1,读取不到socket数据时返回立即0。
#异步:有阻塞么?没有阻塞的。 调用内核的一个方法(callback)(内核帮你把数据读写)
man 2 epoll_create:
man 2 epoll_ctl
strace -ff -o out ./nginx
SOCK_NONBLOCK Set the O_NONBLOCK file status flag on the new open file description. Using this
flag saves extra calls to fcntl(2) to achieve the same result. #fcntl设置也成。
java里设置:ss.configureBlocking(false); #重点 OS NOBLOCK。
C里:
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(listenfd, F_SETFL, O_NONBLOCK); // 设置非阻塞方式
for(i=0; i<wait_fds; ++i ) // for循环中以进程处理epoll事件,更稳定。
{
if( events[i].data.fd == listenfd ){
connfd = accept( listenfd, (struct sockaddr *)&clientaddr, &clilen );
printf("accept return listenfd=%d\n",connfd);
if( connfd < 0 ){
perror("connfd < 0");
exit(1);
}
// 设置非阻塞
if (fcntl( connfd, F_SETFL, fcntl( connfd, F_GETFD, 0)|O_NONBLOCK) == -1){
continue;
}
accept、read、write: -1 不会阻塞。默认recv(5...阻塞。NIO在Java里指:
1)Java New:文件和楼socket都封装成新的东西,可以select统一侦听状态。
2)Unix NOBLOCKING。
BLOCKING的缺点弊端:每客户端、每线程【阻塞】。
man 2 accept #此调用在发生错误时返回-1.若成功则返回一个非负整数标识这个 连接套接字. NOBLOCKING -1
man 2 read #生错误时返回-1,并置 errno 为相应值.在这种情况下无法得知文件偏移位置是否有变化.在读取了一定量的数据后被信号所中断,并返回 -1(且 errno 被设置为EINTR),或者返回已读取的数据量.
1万个连接 1个人发来数据:
accept返回都是-1,来了数据读了一部分后,你又回去处理连接了,数据读不全。于是出现粘包。
但是你在一个循环里,全量遍历O(n)系统调用。
man 2 select:
多少条路、有多少个读的、多少个写的。
select(3,5) # 3有没有连接,5有没有连接。
selec(t3,5,6,7,8,9,10,11) O(1)只需要调一次即可。
accept (3) = 6
recv(5) O(m) #多路复用只能给你返回状态,程序需要自己调用R/W你的IO ,只要自己去读去取就叫同步模型。Netty里全是同步IO模型:无论是在当前线程还是其它线程NIO BIO New IO(指文件、socket一块给弄成一个NewIO),N:还有一个是Noblocking,也就是没来连接时返回-1,读取不到socket数据时返回立即0。
#异步:有阻塞么?没有阻塞的。 调用内核的一个方法(callback)(内核帮你把数据读写)
man 2 epoll_create:
man 2 epoll_ctl
strace -ff -o out ./nginx
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/10568/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2020-5-26 22:39
评论列表