• Linux socket实现非阻塞型通信


    非阻塞通信方法

    对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞与非阻塞。所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待状态, 直到有东西可读或者可写为止。而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待。缺省情况下, 文件描述符处于阻塞状态。在实现聊天室时, server 需要轮流查询与各client 建立的 socket, 一旦可读就将该 socket 中的字符读出来并向所有其他client 发送。并且, server 还要随时查看是否有新的 client 试图建立连接,这样, 如果 server 在任何一个地方阻塞了, 其他 client 发送的内容就会受到影响,得不到服务器的及时响应。新 client 试图建立连接也会受到影响。所以我们在这里不能使用缺省的阻塞的文件工作方式,而需要将文件的工作方式变成非阻塞方式。

    1. fcntl 方法

    函数fcntl()可以用来改变文件I/O操作的工作方式,函数描述如下:

    fcntl( sockfd, F_SETFL, O_NONBLOCK); 
    
    参数说明:
    // sockfd 是要改变状态的文件描述符. 
    // F_SETFL 表明要改变文件描述符的状态 
    // O_NONBLOCK 表示将文件描述符变为非阻塞的.
    
     
    

      

    2. select方法

     select这个方法用来检测一个socket是否有数据到来或是是否有准备好的数据要发送。声明如下:

    select(s, &read_flags, &write_flags, &exec_flags, timer);
    
    参数说明:
    //s             socket的句柄
    //read_flags    读描述字集合。检查socket上是否有数据可读。
    //write_flags   写描述字集合。检查socket上是否已有数据可发送。
    //exec_flags    错误描述字集合。(本教程这儿不介绍)
    //timer         等待某个条件为真时超时时间。
    
    

    使用:

    select(s, &read_flags, &write_flags, NULL, timer);
     
    //exec_flags参数设为null
    

    3.ioctl

    其实有个大牛说使用ioctl出现意想不到的问题:

    有一个非常有迷惑性的做法是:
    u_long has = 1;
    ioctl(m_sock, FIONBIO , &has);
    这个函数会非常无耻的返回你success,但是它实际上很可能什么也没做。

    正确的做法应该是使用fcntl:
    int flags = fcntl(m_sock, F_GETFL, 0);
    fcntl(m_sock, F_SETFL, flags|O_NONBLOCK);

    这真是一个隐蔽的问题,折腾了我两天。线程每每停留在send()调用那里,我始终没怀疑到:
    用ioctl设置FIONBIO成功之后,socket竟然还是阻塞的。

    原文链接:http://blog.csdn.net/wwwsq/article/details/970198

  • 相关阅读:
    keepalived+httpd 高可用
    网卡绑定配置文件
    elk安装
    mysql数据库
    sed
    kvm
    日常巡检
    haproxy
    (6)PY_(study)
    (5)PY_(study)
  • 原文地址:https://www.cnblogs.com/davidzhou11225/p/2454128.html
Copyright © 2020-2023  润新知