_featherbrain 2023-09-22 22:12 采纳率: 0%
浏览 9

为什么在使用printf将udp通信的输出的内容重定向到命名管道中会发生阻塞现象

为什么在使用printf将udp通信的输出的内容重定向到命名管道中会发生阻塞现象,但是使用cout不会?

问题在函数udpRecv中


static void userage()
{
    printf("请输入正确的启动命令:./udp_server serverIP serverPort\n");
}

void *udpRecv(void *arg)
{
    int sock = *(int *)arg;

    // if (bind(sock, (struct sockaddr*)&line, sizeof line) < 0)
    // {
    //     logging(FATAL, "%d : %s\n", errno, strerror(errno));
    // }

    char buff[1024];
    while (true)
    {
        memset(buff, 0, sizeof buff);
        struct sockaddr_in line;
        socklen_t len = sizeof line;
        ssize_t s = recvfrom(sock, buff, sizeof buff, 0, (struct sockaddr *)&line, &len);
        if (s > 0)
        {
            buff[s] = 0;
            // printf("%s\n", buff);   // 会阻塞管道文件 
            std::cout << buff << std::endl;
        }
    }

    return nullptr;
}

void *udpSend(void *arg)
{
    int sock = *(int *)arg;
    struct sockaddr_in line;
    bzero(&line, sizeof line);
    line.sin_family = AF_INET;
    line.sin_port = htons(serverPort);
    line.sin_addr.s_addr = inet_addr(serverIp.c_str());
    std::string sendMessage;
    while (true)
    {
        // perror("请输入您的数据#");
        std::cerr << "请输入您的数据#";
        std::getline(std::cin, sendMessage);

        sendto(sock, sendMessage.c_str(), sendMessage.size(), 0, (struct sockaddr *)&line, sizeof line);
    }

    return nullptr;
}

int main(int argc, char *args[])
{
    if (argc != 3)
    {
        userage();
        exit(1);
    }

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        logging(FATAL, "%d : %s\n", errno, strerror(errno));
        exit(2);
    }

    serverPort = atoi(args[2]);
    serverIp = args[1];

    std::unique_ptr<Thread> reciver(new Thread(1, udpRecv, (void *)&sock));
    std::unique_ptr<Thread> sender(new Thread(2, udpSend, (void *)&sock));

    sender->start();
    reciver->start();

    sender->join();
    reciver->join();

    close(sock);
  
    return 0;
}
  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2023-09-22 23:22
    关注

    引用 皆我百晓生 小程序回复内容作答:
    在使用printf将UDP通信的输出内容重定向到命名管道中时,会发生阻塞现象的原因是,printf函数是线程安全的,它通过互斥锁来保证多个线程对输出流的互斥访问,以防止输出内容交叉混乱。在将输出内容重定向到命名管道中时,由于管道是单向的,写入端需要等待读取端读取数据后才能继续写入,而读取端在调用printf函数时进入了临界区,导致写入端的写入操作被阻塞。

    相比之下,使用std::cout输出到命名管道中不会发生阻塞现象的原因是,std::cout是基于C++的流操作符重载实现的,它会自动处理线程互斥的问题。在多线程环境下,std::cout的输出操作是原子的,所以多个线程可以同时对其进行操作而不会发生阻塞。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月22日