read() 似乎被阻塞,即使传递了O_NONBLOCK标志 [closed]

read() seems to block, even though O_NONBLOCK flag is passed [closed]

提问人:couscous 提问时间:10/27/2023 更新时间:10/27/2023 访问量:48

问:


这个问题是由错别字或无法再现的问题引起的。虽然类似的问题可能在这里是主题,但这个问题的解决方式不太可能帮助未来的读者。

26天前关闭。

我正在尝试使用 UNIX 套接字编写聊天程序。它应该类似于 . 目前,我只测试了一种单向方法,但似乎无法让它工作。nc -U '/tmp/...' -l

我现在的问题是,服务器套接字的读取(显然)阻塞了,我不知道为什么。 仅仅运行服务器套接字代码就应该打印出一个无限的“一个循环”循环,但是当你真正启动它时,它只是在读取时阻塞。

知道为什么吗?

服务器套接字:

// standard includes
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// includes for socket()
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
// include for read()
#include <unistd.h>
// include for fnctl() (non-block)
#include <fcntl.h>

int main() {
  // variables
  int ret;
  int server_socket;
  struct sockaddr_un server_addr;
  char buffer[16]; //16byte transmission
  size_t byteSize;

  // create server_socket
  server_socket = socket(AF_UNIX, SOCK_DGRAM, 0);

  // make server socket non-blocking
    int status = fcntl(server_socket, F_SETFL, fcntl(server_socket, F_GETFL, 0) | O_NONBLOCK);

    if (status == -1){
        perror("calling fcntl");
    }

  // bind server_socket
  server_addr.sun_family = AF_UNIX;
  strcpy(server_addr.sun_path, "/tmp/bidirec.socket");
  ret =
      bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
  if (ret == -1) {
    perror("bind");
    exit(EXIT_FAILURE);
  }

  // masterloop
  while (1) {
        while(read(0, &buffer, 16) > 0) {
            write(server_socket, &buffer, 16);
            memset(&buffer, '0', sizeof(buffer));
            break;
        }
        printf("One loop\n");
    }
}

客户端套接字:

// standard includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// includes for socket()
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
// include for write()
#include <unistd.h>

int main() {
  int ret;
  int client_socket;
  struct sockaddr_un client_addr;
  char buffer[16];

  // create client_socket
  client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);

  // connect to server_socket
  client_addr.sun_family = AF_UNIX;
  strncpy(client_addr.sun_path, "/tmp/bidirec.socket",
          sizeof(client_addr.sun_path) - 1);
  ret = connect(client_socket, (struct sockaddr *)&client_addr,
                sizeof(client_addr));
  if (ret == -1) {
    fprintf(stderr, "The server is down.\n");
    exit(EXIT_FAILURE);
  }

  // masterloop
  while (1) {
      while(read(client_socket, &buffer, 16) > 0) {
            printf("%s", buffer);
            memset(&buffer, 0, sizeof(buffer));
            break;
        }
    }
}
C Linux UNIX 套接字

评论

0赞 Marco Bonelli 10/27/2023
我不确定套接字是如何工作的。你试过用代替吗?O_NONBLOCKrecvMSG_DONTWAITread
0赞 couscous 10/27/2023
@MarcoBonelli我会尝试的,谢谢你的帮助!
2赞 olivecoder 10/27/2023
从此处的 stdin 读取时,它被阻止:read(0, ...
0赞 couscous 10/27/2023
@olivecoder 好的,谢谢。它现在按预期工作。一定是忽略了!
0赞 John Bollinger 10/27/2023
@MarcoBonelli,在插座上工作得很好。在实践中,它们是非阻塞 I/O 的主要主题之一。 服务器套接字也是如此:非阻塞绝对是一回事。O_NONBLOCKaccept()

答:

1赞 couscous 10/27/2023 #1

答:与其让套接字解锁,不如让 fd 用于“stdin”解锁。 第一次读取不依赖于实际的套接字。