zoukankan      html  css  js  c++  java
  • 概念理解-阻塞/非阻塞

    阻塞/非阻塞   主要针对Server端

    同步IO和异步IO的区别就在于:数据访问的时候进程是否阻塞!
    阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回!

    select的阻塞 与 是否设置非阻塞I/O是 没有关系的。
    阻塞
        阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。
        函数只有在得到结果之后才会返回。
    非阻塞
        非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
    设置socket为异步的三种方式
    1、创建socket的时候,指定socket是异步的
    int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);  
    2、使用fcntl函数:
    fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);  
    3、使用ioctl函数:
    int IOFLAG = 1; ioctl(sockfd, FIONBIO, &IOFLAG);  //1:非阻塞 0:阻塞
    /*
    函数名 :int fcntl(int fd, int cmd); 
    参  数 :int fd    -- 文件描述符
    参  数 :int cmd   -- 控制值
    参  数 :flock *lock  -- (参数)
    返回值 :【成功】返回依赖于cmd的值 【错误】返回-1,错误原因存于errno.
    说  明 :fcntl针对文件描述符提供控制。
    */
    int fcntl(int fd, int cmd); 
    int fcntl(int fd, int cmd, long arg); 
    int fcntl(int fd, int cmd, struct flock *lock);
    /*
    函数名 :int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
    参  数 :int maxfd         -- maxfd是要监视的最大的文件描述符值+1;
    参  数 : fd_set *rdset    -- 读文件描述符的集合
    参  数 : fd_set *exset    -- 可写文件描述符集合
    参  数 : fd_set *wrset    -- 异常文件描述符集合
    参  数 : struct timeval *timeout   --超时描述,在一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。
    返回值 :
    说  明 :select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型。
    */
    int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
    
    FD_ZERO(fd_set *fdset); --将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
    FD_SET(fd_set *fdset);  --用于在文件描述符集合中增加一个新的文件描述符。 
    FD_CLR(fd_set *fdset);  --用于在文件描述符集合中删除一个文件描述符。 
    FD_ISSET(int fd,fd_set *fdset); --用于测试指定的文件描述符是否在该集合中。
    // 例子 非阻塞 Tcp Client
    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <sys/select.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { unsigned short port = 8000; char *server_ip = "127.0.0.1"; int sockfd=socket(AF_INET, SOCK_STREAM, 0); //默认非阻塞模式 //int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);// 创建时设置非阻塞模式 if (sockfd<0) { perror("socket error"); exit(-1); } //fcntl设置为非阻塞模式 //fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK); //ioctl设置为非阻塞模式 int IOFLAG = 1; ioctl(sockfd, FIONBIO, &IOFLAG); //1:非阻塞 0:阻塞 struct sockaddr_in server_addr; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(port); inet_pton(AF_INET, server_ip, &server_addr.sin_addr); int ret = 0; int err_log=connect(sockfd,(struct sockaddr*)&server_addr, sizeof(server_addr)); if (0 == err_log) { printf("socket connect succeed. "); ret = 1; } else {
         printf("不要将进程睡眠,而是返回一个错误 err_log = %d ",err_log);
    printf("please get the connect result by select(). "); int times = 0; while (times++ < 5 && ret == 0) { fd_set rfds, wfds; struct timeval tv; FD_ZERO(&rfds);
    FD_ZERO(&wfds); FD_SET(sockfd, &rfds); FD_SET(sockfd, &wfds); tv.tv_sec = 10; tv.tv_usec = 0; int selres = select(sockfd + 1, &rfds, &wfds, NULL, &tv); switch (selres) { case -1: printf("select error "); break; case 0: printf("select time out "); break; default: if (FD_ISSET(sockfd, &rfds) || FD_ISSET(sockfd, &wfds)) { connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)); int err = errno; if (err == EISCONN) { printf("connect finished. "); ret = 1; } else { printf("FD_ISSET(sock_fd, &rfds): %d ", FD_ISSET(sockfd, &rfds)); printf("FD_ISSET(sock_fd, &wfds): %d ", FD_ISSET(sockfd, &wfds)); } } else { printf("other error. "); } } } } if (ret == 1) { char send_buf[512] = "hello"; char recv_buf[512] = ""; if (send(sockfd, send_buf, sizeof(send_buf), 0) > 0) { printf("send "); } } close(sockfd); return 0; }

     结果:

  • 相关阅读:
    4、Cocos2dx 3.0三,找一个小游戏开发Hello World 分析
    Android Bluetooth开发
    详细解析BluetoothAdapter的详细api
    Android 蓝牙( Bluetooth)耳机连接分析及实现
    [Andriod官方API指南]连接之蓝牙
    Android蓝牙A2dp profile的使用
    Android中文API(129) —— AudioManager
    Android中的Audio播放:控制Audio输出通道切换
    JAVA ANDROID SOCKET通信检测(SERVER)连接是否断开
    Android Xfermode 实战 实现圆形、圆角图片
  • 原文地址:https://www.cnblogs.com/osbreak/p/9961101.html
Copyright © 2011-2022 走看看