117.info
人生若只如初见

linux 客户端 Socket 非阻塞connect编程

在Linux中,可以使用非阻塞IO(Non-blocking IO)来实现非阻塞connect的编程。

以下是一个简单的示例代码,演示如何在Linux中使用非阻塞connect进行Socket编程:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main() {
    // 创建Socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        std::cerr << "Failed to create socket." << std::endl;
        return 1;
    }

    // 设置Socket为非阻塞
    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags == -1) {
        std::cerr << "Failed to get socket flags." << std::endl;
        return 1;
    }
    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
        std::cerr << "Failed to set socket to non-blocking mode." << std::endl;
        return 1;
    }

    // 设置连接目标地址
    struct sockaddr_in server_addr{};
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // 尝试非阻塞连接
    int ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (ret == -1) {
        if (errno == EINPROGRESS) {
            // 连接正在进行中,等待连接完成
            fd_set write_fds;
            FD_ZERO(&write_fds);
            FD_SET(sockfd, &write_fds);

            struct timeval timeout{};
            timeout.tv_sec = 5;  // 设置连接超时时间为5秒

            ret = select(sockfd + 1, nullptr, &write_fds, nullptr, &timeout);
            if (ret == -1) {
                std::cerr << "Failed to select." << std::endl;
                return 1;
            } else if (ret == 0) {
                // 连接超时
                std::cerr << "Connect timeout." << std::endl;
                return 1;
            } else {
                // 连接完成,检查连接是否成功
                int error = 0;
                socklen_t len = sizeof(error);
                if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
                    std::cerr << "Failed to get socket option." << std::endl;
                    return 1;
                }
                if (error != 0) {
                    std::cerr << "Failed to connect: " << strerror(error) << std::endl;
                    return 1;
                }
            }
        } else {
            std::cerr << "Failed to connect: " << strerror(errno) << std::endl;
            return 1;
        }
    }

    std::cout << "Connected successfully." << std::endl;

    // 连接成功后,可以进行后续操作

    close(sockfd);

    return 0;
}

在上述代码中,首先创建了一个Socket,并将其设置为非阻塞模式。然后,通过connect函数进行非阻塞连接。如果connect返回-1,并且errno为EINPROGRESS,说明连接正在进行中,此时可以通过select函数等待连接完成。如果select返回0,表示连接超时。如果select返回大于0,说明连接已完成,可以通过getsockopt函数获取连接结果。如果连接成功,可以进行后续操作。

注意,上述代码只是一个简单的示例,实际使用中可能需要根据具体情况进行适当的修改和优化。

未经允许不得转载 » 本文链接:https://www.117.info/ask/fedd0AzsLAwRRB1w.html

推荐文章

  • 如何利用JS日志优化用户体验

    利用JavaScript日志来优化用户体验是一个很好的策略,因为它可以帮助开发者了解应用程序的运行情况,及时发现并解决问题。以下是一些具体的步骤和建议:
    1....

  • 如何用SFTP进行远程备份

    使用SFTP(安全文件传输协议)进行远程备份是一个相对简单且安全的方法。SFTP是SSH协议的一部分,它在文件传输过程中提供加密通信,确保数据的安全性。以下是使用...

  • mount命令挂载设备失败原因

    mount命令挂载设备失败可能有多种原因,以下是一些常见的原因及其解决方法:
    1. 设备路径错误 检查设备路径:确保你输入的设备路径是正确的。例如,/dev/sd...

  • Linux环境下Node.js日志管理策略

    在Linux环境下,Node.js日志管理策略是确保应用程序稳定性和可维护性的关键。以下是一些有效的日志管理策略和实践:
    选择合适的日志库 Winston:最流行的日...

  • Android常用控件Spinner的使用

    Spinner是Android开发中常用的控件之一,用于显示下拉菜单的选项。以下是Spinner的使用方法: 在XML布局文件中添加Spinner控件: 在Java代码中获取Spinner控件的...

  • Ubuntu中安装gcc编译器

    要在Ubuntu中安装GCC编译器,您可以按照以下步骤进行操作: 打开终端 (Ctrl + Alt + T)。
    运行以下命令来更新包列表:sudo apt update
    运行以下命令来...

  • mysql中text,longtext,mediumtext区别

    在MySQL中,text、longtext和mediumtext都是用于存储文本数据类型的列。它们之间的区别如下: text:text类型可以存储最大长度为65,535个字符(约为64KB)的文本...

  • 如何配置jdk环境变量

    要配置JDK环境变量,您需要按照以下步骤进行操作: 首先,下载并安装JDK。
    找到JDK安装目录。默认情况下,JDK安装在"C:\Program Files\Java"(Windows)或"...