我有一个服务器应用程序,它将服务器套接字绑定到 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 以太网设备在套接字仍处于活动状态时被移除时,不会从 select、receive 或 send 函数中收到任何错误,即仍然可以通过客户端套接字发送数据(在客户端连接后从 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");
}
为什么函数 select、poll、send 和 receive - 这里以 send() 为例 - 当 USB 以太网适配器特定的网络设备(插座必须)被删除? 有没有办法检测相关套接字的“有效性”?
更新:
但是,如果通过 getsockopt 和 SO_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;
}
无法理解为什么函数(select、send、write、read 等)不会失败并显示此错误代码,而是有必要明确要求网络接口的存在通过 getsockopt() 调用。