linux 下 BIO、NIO、

BIO时期

在这里插入图片描述

1.客户端发起请求到服务器时,会先到达内核经历三次握手获得连接。
2.内核会给连接分配一个文件描述符:fd1,fd2
3.开启对应线程1/进程1来进行文件描述符fd1内容的读取。(read 命令)

socket在早期是阻塞(blocking)的。(当线程1读取fd1时如果数据还没有到,那这个read命令就不能返回,而是会阻塞着一直等到数据到达,读到了数据才能返回)

所以早期的tomcat7.0 之前的版本也是阻塞的。使用线程读网卡上的连接时,如果连接有数据就拿着数据返回,没有就只能将线程阻塞着后面的方法不能执行。
如果来了新的连接就只能开新的线程进行处理,在JVM中开辟线程的成本(线程栈的默认大小是1MB),且每个CPU核心在单一时间片上只能有一个线程在进行处理。
假设当前正在执行的线程A的数据没到,阻塞了。但是线程B的数据到了,却因为当前的CPU时间片被线程A占有导致CPU浪费。而且线程多了,CPU在线程之间来回切换也会造成浪费。

NIO时期

BIO时期因为硬件性能被浪费,所以内核升级了
在socket命令增加了SOCK_NONBLOCK 类型
在这里插入图片描述
使用man命令查看内核可以调用的函数和工具,man是linux中最常见的帮助命令

首先:yum -y install man man-pages

man 2(2类是查看内核相关的)socket

调用socket()方法时会返回一个文件描述符

就能看到socket命令的相关介绍

SOCKET(2)                  Linux Programmer’s Manual                 SOCKET(2)

NAME
       socket - create an endpoint for communication

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);

DESCRIPTION
       socket() creates an endpoint for communication and returns a descriptor.

       The  domain  argument specifies a communication domain; this selects the protocol family which will be used for communication.  These families are defined in <sys/socket.h>.
       The currently understood formats include:

       Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
       AF_IPX              IPX - Novell protocols
       AF_NETLINK          Kernel user interface device     netlink(7)
       AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
       AF_AX25             Amateur radio AX.25 protocol
       AF_ATMPVC           Access to raw ATM PVCs
       AF_APPLETALK        Appletalk                        ddp(7)
       AF_PACKET           Low level packet interface       packet(7)

       The socket has the indicated type, which specifies the communication semantics.  Currently defined types are:

       SOCK_STREAM     Provides sequenced, reliable, two-way, connection-based byte streams.  An out-of-band data transmission mechanism may be supported.

       SOCK_DGRAM      Supports datagrams (connectionless, unreliable messages of a fixed maximum length).

       SOCK_SEQPACKET  Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer  is  required  to  read  an
                       entire packet with each input system call.

       SOCK_RAW        Provides raw network protocol access.

       SOCK_RDM        Provides a reliable datagram layer that does not guarantee ordering.

       SOCK_PACKET     Obsolete and should not be used in new programs; see packet(7).

       Some socket types may not be implemented by all protocol families; for example, SOCK_SEQPACKET is not implemented for AF_INET.

       Since Linux 2.6.27, the type argument serves a second purpose: in addition to specifying a socket type, it may include the bitwise OR of any of the following values, to mod-
       ify the behavior of socket():

       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.

       SOCK_CLOEXEC    Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor.  See the description of the O_CLOEXEC flag in open(2) for reasons why this may be useful.

       The  protocol specifies a particular protocol to be used with the socket.  Normally only a single protocol exists to support a particular socket type within a given protocol
       family, in which case protocol can be specified as 0.  However, it is possible that many protocols may exist, in which case a particular protocol must be specified  in  this
       manner.   The  protocol  number to use is specific to the “communication domain” in which communication is to take place; see protocols(5).  See getprotoent(3) on how to map
       protocol name strings to protocol numbers.

       Sockets of type SOCK_STREAM are full-duplex byte streams, similar to pipes.  They do not preserve record boundaries.  A stream socket must be in a connected state before any
       data  may  be  sent or received on it.  A connection to another socket is created with a connect(2) call.  Once connected, data may be transferred using read(2) and write(2)
       calls or some variant of the send(2) and recv(2) calls.  When a session has been completed a close(2) may  be  performed.   Out-of-band  data  may  also  be  transmitted  as
       described in send(2) and received as described in recv(2).

       The  communications protocols which implement a SOCK_STREAM ensure that data is not lost or duplicated.  If a piece of data for which the peer protocol has buffer space can-
       not be successfully transmitted within a reasonable length of time, then the connection is considered to be dead.  When SO_KEEPALIVE is enabled on the  socket  the  protocol
       checks  in  a protocol-specific manner if the other end is still alive.  A SIGPIPE signal is raised if a process sends or receives on a broken stream; this causes naive pro-
       cesses, which do not handle the signal, to exit.  SOCK_SEQPACKET sockets employ the same system calls as SOCK_STREAM sockets.  The only difference is that read(2) calls will
       return  only the amount of data requested, and any data remaining in the arriving packet will be discarded.  Also all message boundaries in incoming datagrams are preserved.


可以看到 socker 方法中要求传入一个 int type (指定socket类型
其中有一种叫做 SOCK_NONBLOCK (非阻塞)类型。所以文件描述符就有了nonblock

当有了非阻塞之后就不需要给每个连接开一个线程了,可以用一个线程来轮询处理很多文件描述符的内容。先调用read fd1,如果fd1有数据就处理。处理完调用fd9。如果没有就直接返回,开始调用fd9,不会进行阻塞等待数据到来…
这样就避免了阻塞等待浪费CPU也避免了线程切换带来的浪费。
这个轮询发生在用户态,因为遍历文件描述符和结果处理都是用户空间自己完成所以也称作 同步非阻塞 NIO

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值