c++ - 在 C/C++ 和 std::array 中使用 TCP 时避免阻塞程序

标签 c++ multithreading sockets tcp

我正在使用 Ubuntu,我有一个 C/C++ 应用程序,它使用 WxWidgets 并通过 TCP 发送一个字符串。 只有在路由器和连接正常的情况下它才能正常工作,否则它会卡住,我需要手动退出应用程序。

我是这样调用函数的:

SendCommand ptr;
    if ( ptr.sendcommand(16,16,1) ){
    printf("Porta Aperta\n");
    } else {
    printf("Errore di comunicazione - porta non aperta\n");
    }

这是函数:

int SendCommand::sendcommand(int relay_on, int relay_off, int stop){
    printf("eseguo la funzione nella classe\n");

    std::array<uint8_t, 8> command1;
    std::array<uint8_t, 8> command2;

    switch(relay_on){

    case 16: command1 = {0x58, 0x01, 0x12, 0x00, 0x00, 0x00, 0x10, 0x7B}; // switch on the relay 16
    break;

    }

    switch(relay_off){

    case 16: command2 = {0x58, 0x01, 0x11, 0x00, 0x00, 0x00, 0x10, 0x7A}; // switch off the relay 16
    break;

    }

    int sockfd, n;
    struct sockaddr_in servaddr;

    std::string serveraddr = "192.168.1.4";

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if ( sockfd < 0 )
    {
        cerr << "Error creating socket! " << strerror(errno) << endl;
        return -1;

    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr(serveraddr.c_str());
    servaddr.sin_port = htons(3000);

    if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
    {
        cerr << "Error connecting socket!" << strerror(errno) << endl;
        close(sockfd);
        return -1;
    }

    //Relay #14 per porta bilancia
    printf("Apro la porta\n");

    int bytes_to_send1 = sizeof(command1);
    int bytes_to_send2 = sizeof(command2);
    int bytes_sent1 = 0;
    int bytes_sent2 = 0;

    do
    {
        n = send(sockfd, command1.data() + bytes_sent1, bytes_to_send1 - bytes_sent1, 0);
        if ( n < 0 )
        {
            cerr << "Error writing to socket!" << strerror(errno) << endl;
            close(sockfd);
        }
        bytes_sent1 += n;
    }
    while (bytes_sent1 < bytes_to_send1);

n=0;
sleep(stop);
do
    {
        n = send(sockfd, command2.data() + bytes_sent2, bytes_to_send2 - bytes_sent2, 0);
        if ( n < 0 )
        {
            cerr << "Error writing to socket!" << strerror(errno) << endl;
            close(sockfd);
        }
        bytes_sent2 += n;
    }
    while (bytes_sent2 < bytes_to_send2);
    close(sockfd);
n=0;


return 1;
}

感谢在上一个主题中收到的建议,我使用符号 std::array<uint8_t, 8> command1;定义要通过网络发送的内容的数组,但即使网络出现问题,我也找不到让我的程序正确流动的解决方案。 我尝试使用线程或 fork() 并且它有效,但是有没有其他更简单的解决方案?

附言当它因为没有互联网连接而卡住时,它会阻塞在这里:

if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
    {

        cerr << "Error connecting socket!" << strerror(errno) << endl;
        close(sockfd);
        return -1;
    }

它永远不会进入 if 条件。

最佳答案

几个选项

  1. 使用 Boost ASIO
  2. 线程/进程
  3. 将超时设置为低(例如 - 5 秒),以便阻止相对较少的时间
  4. 设置套接字非阻塞并对其执行epoll(涉及线程)。

对于 2 - 尝试使用标准线程,应该易于使用(您也可以使用异步 + lambda 并使用 futures 简化控制流)。

这样代码看起来更容易阅读。

对于 3 和 4 - 您需要将套接字设置为非阻塞并进行轮询(通过 select 或 epoll)- 参见 fnctl(.., O_NONBLOCK ..) select()。如果没有错误,则可以按原样使用套接字(或者可能从异步返回它并在将来获取)。

关于c++ - 在 C/C++ 和 std::array 中使用 TCP 时避免阻塞程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58509599/

相关文章:

c - 来自 nacl sdk 的 socket() 函数返回 -1

java - Java 套接字延迟 30 秒?

c++ - 是否有任何工具可以在 C++ 中对断言进行编译时检查?

android - SQLite中的多线程数据写入

c++ - 嵌套继承 LNK2001 和 LNK1120 错误

Java——对象的创建和可见性

multithreading - 可以从多个线程安全地访问静态数组吗?

java.net.SocketTimeoutException : Read timed out

c++ - 如何划分位集?

c++ - "Interactive"在 C++ 中休眠