c/c++ 阻塞和非阻塞,fcntl应用

调用open函数时,可以指定打开的文件描述符是以阻塞方式还是以非阻塞方式。
阻塞概念:read函数在读设备或者管道,或者socket的时候,默认是阻塞的,也就是说,对方如果没有发送数据过来,则read函数就会一直等待数据过来,从代码的角度来说,就是read函数后面的代码不会被执行。
非阻塞概念:read函数在读设备或者管道,或者socket的时候,对方如果没有发送数据过来,read函数也会立即返回,从代码的角度来说,就是read函数后面的代码会马上被执行。

  • 非阻塞方式打开:

    int fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
  • 阻塞方式打开:

    int fd = open("/dev/tty", O_RDWR);

标准输入输出和错误,实际使用的文件是:/dev/tty,所以下面的例子用这个文件演示。
当用非阻塞的时候,如果没有read到,函数不会等待,会立即返回,返回值是【-1】,这时errno的值为【11】,用perror打印出来的信息是【Resource temporarily unavailable】
例子:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char* argv[]){
  int fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
 
  char buf[256];
  while(1){
    int ret = read(fd, buf, sizeof buf);
    if(ret < 0){
      perror("read:");
      printf("ret :%d\n", ret);
    }
    printf("buf is:%s", buf);
    printf("haha\n");
  }
}

除了使用【O_NONBLOCK】外,还可以使用fcntl函数,原型如下:

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

F_GETFD (void)
   Return  (as  the function result) the file descriptor flags; arg
   is ignored.
F_SETFD (int)
   Set the file descriptor flags to the value specified by arg.

例子:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char* argv[]){
  int fd = open("/dev/tty", O_RDWR);

  //先取得fd的flag
  int flags = fcntl(fd, F_GETFL);
  //再在原来fd的flag的基础上,设置上O_NONBLOCK
  flags |= O_NONBLOCK;
  //让新的flag生效
  fcntl(fd, F_SETFL, flags);
  
  char buf[256];
  while(1){
    int ret = read(fd, buf, sizeof buf);
    if(ret < 0){
      perror("read:");
      printf("ret :%d\n", ret);
    }
    printf("buf is:%s", buf);
    printf("haha\n");
    sleep(1);
  }
}

c/c++ 学习互助QQ群:877684253

1414315-20181106214320230-961379709.jpg

本人微信:xiaoshitou5854

转载于:https://www.cnblogs.com/xiaoshiwang/p/10759508.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用C++实现SECS/GEM通信的简单案例: ``` #include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> using namespace std; int main() { // 创建socket对象 int sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror("socket"); return -1; } // 设置socket为非阻塞模式 int flags = fcntl(sock_fd, F_GETFL, 0); fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK); // 设置server地址和端口号 struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(5000); // 连接到server int ret = connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (ret < 0 && errno != EINPROGRESS) { perror("connect"); return -1; } // 发送SECS/GEM消息 const char* message = "S1F1E1"; int send_len = send(sock_fd, message, strlen(message), 0); if (send_len < 0) { perror("send"); return -1; } // 接收SECS/GEM消息 char buffer[1024]; int recv_len = recv(sock_fd, buffer, sizeof(buffer), 0); if (recv_len < 0) { perror("recv"); return -1; } // 打印接收的消息 buffer[recv_len] = '\0'; cout << "Received message: " << buffer << endl; // 关闭socket close(sock_fd); return 0; } ``` 上述代码是一个使用C++实现SECS/GEM通信的简单案例,该程序连接到一个IP地址为127.0.0.1,端口号为5000的SECS/GEM服务器,发送一个S1F1E1的SECS/GEM消息,并接收服务器返回的SECS/GEM消息,并打印接收到的消息。需要注意的是,该程序是一个简单的示例,具体的SECS/GEM通信需要根据具体的协议版本和变种来进行相应的实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值