gpt4 book ai didi

c - 如何选择用于执行主机名查找的接口(interface)

转载 作者:行者123 更新时间:2023-12-03 09:50:52 24 4
gpt4 key购买 nike

我正在使用嵌入在运行 Linux 和 BusyBox 的设备中的应用程序。硬件有2个通信接口(interface):Wi-Fi和3G。

在每次连接中,应用程序必须首先尝试使用 wi-fi 连接,如果失败,应用程序将使用 3G 再次尝试。

我强制连接使用选定的接口(interface),像这样绑定(bind)它:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <net/if.h>

static void resolveDns(const char *hostname, struct addrinfo **destInfo)
{
int err;
struct addrinfo hints;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;

if ((err = getaddrinfo(hostname, "80", &hints, destInfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(err));
exit(EXIT_FAILURE);
}

struct sockaddr_in *addr = (struct sockaddr_in *)((*destInfo)->ai_addr);
printf("Destination IP: %s\n", inet_ntoa(addr->sin_addr));
}

static void getComInterface(const char *iface, struct ifreq *ifr)
{
ifr->ifr_addr.sa_family = AF_INET;
strcpy(ifr->ifr_name, iface);

int sock = socket(AF_INET, SOCK_DGRAM, 0);
int err = ioctl(sock, SIOCGIFADDR, ifr);
close(sock);

if (err) {
fprintf(stderr, "ioctl error: %d\n", err);
exit(EXIT_FAILURE);
}

printf("Interface IP: %s\n", inet_ntoa(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr));
}

int main()
{
int err;

struct ifreq ifr;
getComInterface("wlan0", &ifr);

struct addrinfo *destInfo;
resolveDns("www.google.com", &destInfo);

int s = socket(AF_INET, SOCK_STREAM, 0);
err = bind(s, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
if (err) {
fprintf(stderr, "bind error = %d, %d\n", err, errno);
exit(EXIT_FAILURE);
}

err = connect(s, destInfo->ai_addr, destInfo->ai_addrlen);
if (err) {
fprintf(stderr, "connect error = %d, %d \n", err, errno);
exit(EXIT_FAILURE);
}

printf("Ok!\n");

freeaddrinfo(destInfo);
close(s);
return EXIT_SUCCESS;
}

但这并不能解决DNS查找中的问题。

有没有办法强制 getaddrinfo 使用选定的接口(interface)?或者,更好的是,有没有一种方法可以强制所有连接使用选定的接口(interface)而不断开其他连接?

P.S.:如果您知道如何在更复杂的 SO 中执行此操作,例如 Ubuntu,请分享您的解决方案。

谢谢

最佳答案

恐怕仅通过标准 C 库是无法做到的,即您需要更改默认网关,并为每个连接设置网关。请考虑以下伪代码:

  • 系统启动:

    • 通过wifi建立连接
    • 通过3G建立连接
    • 将wifi接口(interface)配置为默认网关
  • 关于新的连接请求:

    • 进行 DNS 查找(通过默认路由进行)
      • 如果成功
        • 保存IP地址和文件描述符
        • 通过作为当前网关的接口(interface)配置到此 IP 的路由
        • 打开到 IP 地址的套接字,流量将通过给定的接口(interface)
      • 如果没有
        • 将默认网关更改为另一个接口(interface)(3G),然后重试
  • 断开连接时:

    • 通过断开连接的文件描述符找到IP地址
    • 从路由表中删除IP
    • 转到“On new connection request”(这取决于您的应用程序逻辑)

这样,您将能够更改新连接的默认网关,但保留现有连接的默认网关。

路由表的更改可以通过 Linux shell 命令完成,例如 ip route 等。它们可以通过 system 从 C 启动,例如system( "ip route show");您还可以编写具有更复杂逻辑的脚本并从您的 C 代码启动它们。

但是,这个解决方案有一个缺陷,通常,如果您当前的界面没有互联网连接,这意味着所有使用该接口(interface)的连接最终都可能失败。

关于c - 如何选择用于执行主机名查找的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63653312/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com