虽然绑定的网络接口不再存在,但套接字上没有错误

问题描述 投票:0回答:0

我有一个服务器应用程序,它将服务器套接字绑定到 Linux 网络设备,该设备是在我将相应的 USB-以太网适配器热插拔到本地计算机的 USB 端口后创建的:

// Bind the socket to the network device corresponding to the USB Ethernet adapter
const char *device = "enxf8e43b4f4bd2";
if (setsockopt(server_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)) < 0) {
    std::cerr << "Failed to bind to device\n";
    close(server_fd);
    return 1;
}

但是,当 USB 以太网设备在套接字仍处于活动状态时被移除时,不会从 selectreceivesend 函数中收到任何错误,即仍然可以通过客户端套接字发送数据(在客户端连接后从 accept() 调用中获得)没有任何错误,尽管相应的网络设备在数据发送之前被删除(适当的设备条目/sys/bus/usb/该 USB 以太网适配器的设备 路径已删除;ip link 命令也不再列出网络设备):

...
printf("Remove the USP-Ethernet adapter first and press any key afterwards to send data to the client\n");
std::getchar();
int number = send(client_socket, hello_reply, strlen(hello_reply), 0);
if (number == -1) {
            // I would expect this branch to get executed, but it doesn't.
            std::cout << "send error: " << strerror(errno) << std::endl;
            close(client_socket);
} else if (number == 0) {
            // This branch isn't also executed.
            printf("nothing sent\n");
} else {
            // This branch gets executed and indicates the number of bytes being sent although the
            // network device associated with the USB Ethernet adapter isn't available anymore.
            // Any explaination on this?
            printf("number of bytes sent to client: %d\n", number);
}...

还通过以下代码明确查询套接字上的任何错误,并不表示套接字上有任何错误:

// check the validity state of the client socket
int error = 0;
socklen_t error_len = sizeof(error);
if (getsockopt(client_socket, SOL_SOCKET, SO_ERROR, &error, &error_len) < 0) {
    std::cerr << "Error getting socket options: " << strerror(errno) << std::endl;
    return -1;
}
if (error != 0) {
    std::cout << "client socket socket error: " << strerror(error) << std::endl;
    return -1;
} else {
    // This branch gets executed.
    printf("client socket is ok\n");
}

为什么函数 selectpollsendreceive - 这里以 send() 为例 - 当 USB 以太网适配器特定的网络设备(插座必须)被删除? 有没有办法检测相关套接字的“有效性”?


更新:

但是,如果通过 getsockoptSO_BINDTODEVICE 选项明确查询客户端套接字在删除关联的 USB 以太网设备后绑定到哪个网络设备,则会返回错误代码 ENODEV(= 没有此类设备) :

    if (getsockopt(client_socket, SOL_SOCKET, SO_BINDTODEVICE, &iface, &len) == -1) {
    // Path entered after the USB Ethernet device was removed -> ENODEV is set.
    if(errno == ENODEV)  {
        std::cerr << "Error: " << strerror(errno) << std::endl;
    }
    close(client_socket);
    return 1;
}

无法理解为什么函数(selectsendwriteread 等)不会失败并显示此错误代码,而是有必要明确要求网络接口的存在通过 getsockopt() 调用。

linux sockets network-programming usb c-api
© www.soinside.com 2019 - 2024. All rights reserved.