精华内容
下载资源
问答
  • 设置socket的O_NONBLOCK以及TCP_NODELAY 1. no-blocking 将socket设置为no-blocking意味着socket收发数据都是非阻塞的,相比于阻塞方式,需要特殊处理这个错误码:EWOULDBLOCK or EAGAIN(这两个错误码是一样的,都...

    1. no-blocking

    将socket设置为no-blocking意味着socket收发数据都是非阻塞的,相比于阻塞方式,需要特殊处理这个错误码:EWOULDBLOCK or EAGAIN(这两个错误码是一样的,都是35),进行重试或者重新调度。

    将socket设置非阻塞有多种方法,下面会一一汇总。

    1.1 fcntl设置O_NONBLOCK

    POSIX的fcntl用的比较广泛,兼容性也比较好,优先推荐使用fcntl来设置,缺点是需要两次系统调用:get、set:

        /* Change the socket into non-blocking state F_SETFL is a command saying set flag and flag is 0_NONBLOCK */                                          
        const int flags = fcntl(fd, F_GETFL, 0);
        if (flags < 0) {
            return flags;
        }
        if (flags & O_NONBLOCK) {
            return 0;
        }
        return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    }
    

    1.2 使用socket自带的函数

    该方法优点是简单,缺点是兼容性不太好,要求Linux内核版本高于2.6.27才可以使用:

       // client side
       int socketfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    
       // server side - see man page for accept4 under linux 
       int socketfd = accept4( ... , SOCK_NONBLOCK);
    

    1.3 ioctl设置FIONBIO

    ioctl最先在UNIX系统上使用,跨平台兼容性比较差,各个系统中该系统调用的行为是不一致的,不建议使用该方式:

        int opt = 1;
        int status = ioctl(fd, FIONBIO, &opt);
    

    2. no-delay

    Nagle算法是为了减少更多的网络小数据包:如果数据小于一个限制(通常是MSS),等待接收到之前发送的数据包的ACK,在同一时间内积累用户的数据,然后发送累积的数据。
    Nagle算法有助于像telnet这样的应用程序。然而,等待ACK可能会增加发送流数据时的延迟。此外,如果接收方实现了“延迟确认策略”,它将导致临时的死锁情况。在这种情况下,禁用Nagle的算法是更好的选择,可以通过设置TCP_NODELAY禁用Nagle算法。

        int opt = 1;
        int status = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
    

    3. ref

    • https://stackoverflow.com/questions/1543466/how-do-i-change-a-tcp-socket-to-be-non-blocking/22339017
    • http://senlinzhan.github.io/2017/02/10/Linux%E7%9A%84TCP-CORK/
    展开全文
  • 在创建socket函数中的第二个参数types用来指定服务类型,在Linux2.6.17版本起,除了之前的SOCK_STREAM(流式服务)、SOCK_UGRAM(数据报服务)以外,又增加了SOCK_NONBLOCK和SOCK_CLOEXEC,分别表示将创建的socket设置为...

    http://www.cnblogs.com/sunada2005/p/3591378.html

    谓阻塞方式的意思是指,当试图对该文件描述符进行读写时,如果当时没有东西可读,或者暂时不可写,程序就进入等待状态,直到有东西可读或者可写为止。

    而对于非阻塞状态,如果没有东西可读,或者不可写,读写函数马上返回,而不会等待。

    非阻塞,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高

    简单的讲,阻塞就是GET,非阻塞就是PUT

    阻塞好控制,不发送完数据程序不会走下去。但是对性能有影响。
    非阻塞不太好控制,可能和能力有关,但是性能会得到很大提升。

    阻塞式的编程方便。
    非阻塞的编程不方便,需要程序员处理各种返回值

    阻塞处理简单,非阻塞处理复杂

    阻塞效率低,非阻塞效率高

    阻塞模式,常见的通信模型为多线程模型,服务端accept之后,对每个socket创建一个线程去recv。逻辑上简单,适用于并发量小(客户端数目少),连续传输大数据量的情况下,比如文件服务器。还有就是在客户端recv服务器消息的时候也经常用,因为客户端就一个socket,用阻塞模式不影响效率,而且编程逻辑上要简单得多。

    非阻塞模式,常见的通信模型为select模型和IOCP模型。适用于高并发,数据量小的情况,比如聊天室。客户端多的情况下,如果采用阻塞模式,需要开很多线程,影响效率。另外,客户端一般不采用非阻塞模式。

     

    一、socket阻塞和非阻塞有哪些不同
    1. 建立连接
    阻塞方式下,connect首先发送SYN请求到服务器,当客户端收到服务器返回的SYN的确认时,则connect返回,否则的话一直阻塞。

    非阻塞方式,connect将启用TCP协议的三次握手,但是connect函数并不等待连接建立好才返回,而是立即返回,返回的错误码为EINPROGRESS,表示正在进行某种过程。

    2. 接收连接
    阻塞模式下调用accept()函数,而且没有新连接时,进程会进入睡眠状态,直到有可用的连接,才返回。

    非阻塞模式下调用accept()函数立即返回,有连接返回客户端套接字描述符,没有新连接时,将返回EWOULDBLOCK错误码,表示本来应该阻塞。

    3. 读操作
    阻塞模式下调用read(),recv()等读套接字函数会一直阻塞住,直到有数据到来才返回。当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数。当sockt的接收缓冲区中的数据大于期望读取的字节数时,读取期望读取的字节数,返回实际读取的长度。

    对于非阻塞socket而言,socket的接收缓冲区中有没有数据,read调用都会立刻返回。接收缓冲区中有数据时,与阻塞socket有数据的情况是一样的,如果接收缓冲区中没有数据,则返回错误号为EWOULDBLOCK,表示该操作本来应该阻塞的,但是由于本socket为非阻塞的socket,因此立刻返回。遇到这样的情况,可以在下次接着去尝试读取。如果返回值是其它负值,则表明读取错误。

    因此,非阻塞的re

    4.写操作
    对于阻塞Socket而言,如果发送缓冲区没有空间或者空间不足的话,write操作会直接阻塞住,如果有足够空间,则拷贝所有数据到发送缓冲区,然后返回.

    对于写操作write,原理和read是类似的,非阻塞socket在发送缓冲区没有空间时会直接返回错误号EWOULDBLOCK,表示没有空间可写数据,如果错误号是别的值,则表明发送失败。如果发送缓冲区中有足够空间或者是不足以拷贝所有待发送数据的空间的话,则拷贝前面N个能够容纳的数据,返回实际拷贝的字节数。
    尤其注意非阻塞的socket,在建立连接时要兼容处理返回EINPROGRESS情况,在接收连接、读操作、写操作时要兼容处理返回EWOULDBLOCK错误码的情况,以上情况并非连接异常,而是网络延时或者套接字缓冲区满造成的,一般不宜做异常处理(如返回异常关闭套接字)。

    简单点理解就是:

    同步,就是我调用一个功能,该功能没有结束前,我死等结果。
    异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)。
    阻塞,就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
    非阻塞,就是调用我(函数),我(函数)立即返回,通过select通知调用者
    同步IO和异步IO的区别就在于:数据拷贝的时候进程是否阻塞
    阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回
    --------------------- 
    原文:https://blog.csdn.net/mayue_web/article/details/82873115 

     

    (一)socket阻塞与非阻塞问题

    在创建socket函数中的第二个参数types用来指定服务类型,在Linux2.6.17版本起,除了之前的SOCK_STREAM(流式服务)、SOCK_UGRAM(数据报服务)以外,又增加了SOCK_NONBLOCK和SOCK_CLOEXEC,分别表示将创建的socket设置为非阻塞的和用fork创建的子进程在子进程中关闭该socket;

    第一个问题:如何将socket设置为非阻塞的?

    第一种,fcntl系统调用函数是用来控制文件描述符常用的属性和行为,通过此函数可以修改socket属性;

    #include <fcntl.h>
    int fcntl(int fd,int cmd,...)
    fd是要被操作的文件描述符,cmd参数指定执行何种类型操作,常见的cmd有以下几种:

    获取文件描述符标志  ----> F_GETFD   设置文件名描述符标志----->F_SETFD 

    获取文件描述符状态标志--->F_GETFL 设置文件名描述符状态标志----->F_SETFL

    修改socket为非阻塞socket

    int flags = fcntl(sockfd,F_GETFL,0);

    fcntl(sockfd,F_SETFL,flags | SOCK_NONOBLOCK);

    第二种:直接在创建socket时设置

    int sockfd= socket(AF_INET,SOCK_STREAM | SOCK_NONOBLOCK,0);

    注意accept返回的socket也是阻塞的,应用accept4函数将最后一个参数设置为SOCK_NONOBLOCK

    int accept4(sockfd,(struct sockaddr*)&cli,&len,SOCK_NONBLOCK);

    第二个问题:在完成三次握手之后,网络异常(掉线)或者客户端正常退出,对accept是否会有影响?

    netstat -nt | grep hostport 查看此端口的TCP连接状态

    掉线以及客户端退出都不会影响accept调用返回,由于accept只是从监听队列中取出连接,而不论连接状态处于何种状态,更不关心网络状态.不会因为监听队列中socket状态的变化而决定accept是否能调用成功。

    第三个问题:关于socket选项的知识

    #include <sys/socket.h>

    int getsockopt(int sockfd,int level,int option_name,void *option_value,socklen_t *restrict option_len);

    int setsockopt(int sockfd,int level,int option_name,const void *option_value,socklen_t  option_len);

    level指定要操作那个协议的选项,通用socket选项的level是SOL_SOCKET,option_name 是指定选项的名字

    常用的通用socket选项有:SO_REUSEADDR 重用本地址 、SO_RCVBUF --->TCP接受缓冲区大小、SO_SNDBUF --->TCP发送缓冲区大小、SO_LINGER 若有数据待发送则延缓关闭、TCP_MAXSEG  ---> TCP最大报文段大小 上述这几个必须在listen调用之前设置才有效。

    socket选项一:SO_REUSEADDR

    通过设置socket此选项可以强制使用处于time_wait状态的连接占用的socket地址,也可以通过修改内核参数/proc/sys/net/ipv4/tcp_tw_recycle来快速回收被关闭的连接socket,从而使得TCP连接根本不进入time_wait状态。进而允许本次程序重用socket地址

    socket选项二:SO_RCVBUF SO_SNDBUF

    SO_RCVBUF:TCP接受缓冲区的大小最小值为256字节 ,如果我们修改此大小小于256字节时,系统会忽略此次设置,最小值还是256字节

    SO_SNDBUF:TCP发送缓冲区大小最小值是2048字节,是为了保证一个TCP连接有足够的空闲缓冲区处理拥塞,如果我们修改此大小,系统会将我们设置的值翻倍

    也可以修改内核参数:/proc/sys/net/ipv4/tcp_rmem、/proc/sys/net/ipv4/tcp_wmem来强制TCP接受和发送缓冲区的大小没有最小值限制。

    选项三:SO_LINGER

    SO_LINGER用于控制close系统调用在关闭TCP连接时的行为,默认情况下,当我们使用close系统调用关闭socket时会立即返回,TCP模块将该socket对应的发送缓冲区的残留数据发送给对方

    在设置此选项时,需要向函数传递Linger结构体:

    struct linger

    {

      int l_onoff;//0未开启,1开启

      int l_linger;//滞留时间 

    }

    根据linger结构体中两个变量的值不同,close调用会有不同的方式

    情况一:l_onoff==0;此时SO_LINGER不起作用,close使用默认行为关闭socket;

    情况二:l_onoff != 0 && l_linger == 0;此时close调用立即返回,将该socket对应的发送缓冲区的数据发给对方,同时给对方发送一个复位报文段。这种情况给服务器提供了一个异常终止连接的方法;

    情况三:l_onoff != 0 && l_linger >0;此时close的行为取决于两个条件:1.该socket对应的发送缓冲区是否还有残留数据;2.该socket是阻塞的还是非阻塞的;

    对于阻塞的socket,close将等待一段长为l_linger的时间等TCP模块将发送缓冲区的数据发给对方并得到对方确认,返回-1并设置EWOULDBLOCK(不需要重新读写);

    对于非阻塞的socket,close立即返回,此时需要根据返回值和error来判断残留数据是否发送完毕;如果tcp缓冲区还有数据需要发送,数据能够正确的发送到对端;在发送的最后一个包会加FIN标志;如果另一端也要关闭发FIN时,本端就会发RST,因为本端的SOCKET已经关了。
    --------------------- 
    作者:zhangyin_blog 
    来源:CSDN 
    原文:https://blog.csdn.net/weixin_41966991/article/details/81942349 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • Linux 阻塞/非阻塞介绍 NONBLOCK–非阻塞标志 阻塞操作: 当执行设备操作时:当设备无法立刻满足用户的读写操作时,直接将进程挂起,挂起的进程进入休眠状态,并从调度器的运行队列中移走。直到满足可操作的条件后...

    Linux 阻塞/非阻塞介绍 NONBLOCK–非阻塞标志

    阻塞操作:

    当执行设备操作时:当设备无法立刻满足用户的读写操作时,直接将进程挂起,挂起的进程进入休眠状态,并从调度器的运行队列中移走。直到满足可操作的条件后唤醒进程,重新执行操作。

    举例

    在阻塞型驱动程序中,如果调用read, 但设备无数据或数据不足时,进程阻塞,当数据充足时,唤醒阻塞进程。

    非阻塞操作:

    Linux 中一切皆文件,阻塞方式是文件读写操作的默认方式。 但可以使用O_NONBLOCK 标志人为设置读写操作为非阻塞方式(可以使用fcntl() 函数实现)。

    非阻塞方式下,如果读操作时设备数据不充足,或写数据时缓冲区空间不足,系统只是简单返回-EAGAIN, 并不会阻塞线程。

    --------温馨提示:主要用于个人理解和学习,如有错误欢迎提出-------------

    展开全文
  • O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非搁置模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会搁置程序动作,直到有数据或写入完成。 它们的差别在于设立O_NDELAY会使I/O函式...

    O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非搁置模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会搁置程序动作,直到有数据或写入完成。

    它们的差别在于设立O_NDELAY会使I/O函式马上回传0,但是又衍生出一个问题,因为读取到档案结尾时所回传的也是0,这样无法得知是哪中情况;因此,O_NONBLOCK就产生出来,它在读取不到数据时会回传-1,并且设置errno为EAGAIN。

    不过需要注意的是,在GNU C中O_NDELAY只是为了与BSD的程序兼容,实际上是使用O_NONBLOCK作为宏定义,而且O_NONBLOCK除了在ioctl中使用,还可以在open时设定。

    TCP/IP协议中针对TCP默认开启了Nagle算法。Nagle算法通过减少需要传输的数据包,来优化网络。在内核实现中,数据包的发送和接受会先做缓存,分别对应于写缓存和读缓存。

    启动TCP_NODELAY,就意味着禁用了Nagle算法,允许小包的发送。对于延时敏感型,同时数据传输量比较小的应用,开启TCP_NODELAY选项无疑是一个正确的选择。比如,对于SSH会话,用户在远程敲击键盘发出指令的速度相对于网络带宽能力来说,绝对不是在一个量级上的,所以数据传输非常少;而又要求用户的输入能够及时获得返回,有较低的延时。如果开启了Nagle算法,就很可能出现频繁的延时,导致用户体验极差。当然,你也可以选择在应用层进行buffer,比如使用java中的buffered stream,尽可能地将大包写入到内核的写缓存进行发送;vectored I/O(writev接口)也是个不错的选择。

    对于关闭TCP_NODELAY,则是应用了Nagle算法。数据只有在写缓存中累积到一定量之后,才会被发送出去,这样明显提高了网络利用率(实际传输数据payload与协议头的比例大大提高)。但是这又不可避免地增加了延时;与TCP delayed ack这个特性结合,这个问题会更加显著,延时基本在40ms左右。当然这个问题只有在连续进行两次写操作的时候,才会暴露出来。

    连续进行多次对小数据包的写操作,然后进行读操作,本身就不是一个好的网络编程模式;在应用层就应该进行优化。

    对于既要求低延时,又有大量小数据传输,还同时想提高网络利用率的应用,大概只能用UDP自己在应用层来实现可靠性保证了。好像企鹅家就是这么干的。

    展开全文
  • (1)调用open获得描述符,并指定O_NONBLOCK标志 (2)对已经打开的文件描述符,调用fcntl,打开O_NONBLOCK文件状态标志。 flags = fcntl( s, F_GETFL, 0 ) ) fcntl( s, F_SETFL, flags | O_NONBLOCK ) ...
  • 在学习获取设备信息的四种方式(查询,休眠-唤醒,poll,select)时,发现在使用poll和select时,需要在open时使用1O_NONBLOCK1参数。由于我刚开始没注意这个问题,导致实验现象不正常,这里记录一下。 2.不使用O_...
  • Linux:非阻塞O_NONBLOCK与O_NDELAY的区别

    万次阅读 2019-06-05 23:16:29
    O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非阻塞模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会阻塞等待。 它们的差别在于:在读操作时,如果读不到数据,O_NDELAY会使I/O函数...
  • linux下 O_NONBLOCK与O_NDELAY的区别

    千次阅读 2020-05-26 22:23:02
    在上一篇文章《linux下“阻塞”与“非阻塞”的定义及区别》中,我们分析了阻塞和非阻塞两种模式,与“非阻塞模式”相关的有两个 标志,就是 O_NONBLOCK与O_NDELAY,这两种参数的结果都是使I/O操作设置为“非阻塞模式...
  • 转载于:https://www.cnblogs.com/jest549/p/11364983.html
  • 如果设置了 O_NONBLOCK 标志,read 和 write 的行为是不同的 ,如果进程没有数据就绪时调用了 read , 或者在缓冲区没有空间时调用了 write ,系统只是简单的返回 -EAGAIN,而不会阻塞进程. 实例 --- 读阻塞的...
  • 设置O_NONBLOCK

    千次阅读 2017-12-08 07:13:51
    int evutil_make_socket_nonblocking... if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {  event_warn("fcntl(%d, F_SETFL)", fd);  return -1;  }  }  } #endif  return 0; }
  • fcntl系统调用可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种... } // 设置非堵塞,作要么成功,要么立即返回错误,不被阻塞 fcntl(rsck, F_SETFL, O_NONBLOCK | fcntl(rsck, F_GETFL, 0));
  • O_NONBLOCK与O_NDELAY有何不同

    千次阅读 2017-12-07 10:05:46
    http://blog.csdn.net/qilu0882/article/details/40980843
  • 用F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK;  方法2、recv,send 系列的参数。(读取,发送时,临时将sockfd或filefd设置为非阻塞)  方法一的实现  fcntl 函数可以将一个socket 句柄设置成非阻塞...
  • 用F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK;  方法2、recv,send 系列的参数。(读取,发送时,临时将sockfd或filefd设置为非阻塞)  方法一的实现  fcntl 函数可以将一个socket 句柄设置成非阻塞...
  • NONBLOCK 是同步IO的结果, 由自己进行处理, 比如errno == EAGAIN / EWOULDBLOCK / EINPROCESS 等. 这里就使用了NONBLOCK :  边缘模式EPOLLET EPOLLOUT简单例子   OVERLAPPED 是异步IO , 由系统来完成读写...
  • <div><p>This is a fix for #1777 <p>ServerSocket#accept_nonblock should return a Sockaddr with the remote port, not the local port.</p><p>该提问来源于开源项目:jruby/jruby</p></div>
  • 28-nonblock.rar

    2018-12-17 13:53:53
    网络编程从大的方面说就是对信息的发送到接收,中间传输为物理线路的作用。网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到...
  •  boundaries, with writes by other processes, whether or not the O_NONBLOCK flag of the file status flags is  set.  * If the O_NONBLOCK flag is clear, a write request may cause the thread to ...
  • O_NONBLOCK,fcntl 非阻塞io读取键盘鼠标

    千次阅读 2016-08-29 20:14:36
     O_DIRECT, O_NOATIME, and O_NONBLOCK flags. //O_NONBLOCK,fcntl 非阻塞io读取键盘鼠标 #include #include #include #include #include #include   ...
  • <p>When I do not use <code>O_NONBLOCK, then the whole of 8762 bytes are written in a single write and everything works as expected. <p><strong>C Client Socket Connection</strong></p> <pre><code> if ...
  • 使用O_NONBLOCK方式打开设备文件

    千次阅读 2015-12-28 16:58:05
    open函数 #include <fcntl.h>int open(const char *pathname, int ...O_NONBLOCK 如果pathname指的是一个FIFO文件、块设备文件或字符设备文件,则此选项将文件的本次打开操作和后续的I/O操作设置为非阻塞模式
  • O_NONBLOCK与O_NDELAY有何不同?

    千次阅读 2016-02-14 14:52:38
    O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非搁置模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会搁置程序动作,直到有数据或写入完成。 它们的差别在于设立O_NDELAY会使I/O函式...
  • 特点一:不指定O_NONBLOCK(即open没有位或O_NONBLOCK) 1、open以只读方式打开FIFO时,要阻塞到某个进程为写而打开此FIFO 2、open以只写方式打开FIFO时,要阻塞到某个进程为读而打开此FIFO。 3、open以只读...
  • select+NONBLOCK

    千次阅读 2011-02-12 10:43:00
    将socket设成NONBLOCK(使用fcntl函数),然后select到该socket可读之后,使用read/recv来读取数据。当函数返回-1,同时errno是EAGAIN或EWOULDBLOCK的时候,表示数据已经全部读取完毕。   实验结论:   ...
  • readfd = open(FIFO_FILE, O_RDONLY | O_NONBLOCK, 0 ); int writefd = open(FIFO_FILE, O_WRONLY | O_NONBLOCK, 0 ); 上述代码中的两个open不能反过来,不然会报错: No such device or address 注意到...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,743
精华内容 13,897
关键字:

NONBLOCK