Mac下同时使用Ethernet与Wifi接口,如何用C/Python指定接口发请求?
Absolutely! You can target specific network interfaces (Ethernet/Wi-Fi) for individual HTTP requests on macOS. The core idea is to bind your network connection to the IP address of the desired interface before sending the request—since each interface has its own unique IP on your system.
Prerequisite: Find Your Interface IPs
First, grab the IP addresses of your Ethernet and Wi-Fi interfaces. Run these commands in Terminal:
- Wi-Fi (usually
en0on modern Macs):ipconfig getifaddr en0 - Ethernet (often
en1oren2, orusb0for USB adapters):ipconfig getifaddr en1
If these don’t match your setup, run ifconfig to list all interfaces and their IPs.
Python Implementation
The requests library can be customized to use a specific source IP with a custom adapter. Here’s a practical example:
Example: Send Requests via Wi-Fi and Ethernet Separately
import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager class SourceIPAdapter(HTTPAdapter): def __init__(self, source_ip, **kwargs): self.source_ip = source_ip super().__init__(**kwargs) def init_poolmanager(self, connections, maxsize, block=False): self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, source_address=(self.source_ip, 0) # 0 = use random port ) # Replace these with your actual interface IPs WIFI_IP = "192.168.1.100" ETHERNET_IP = "192.168.0.50" # Send request via Wi-Fi wifi_session = requests.Session() wifi_session.mount("http://", SourceIPAdapter(WIFI_IP)) wifi_session.mount("https://", SourceIPAdapter(WIFI_IP)) wifi_response = wifi_session.get("https://api.ipify.org") print(f"Wi-Fi request external IP: {wifi_response.text}") # Send request via Ethernet ethernet_session = requests.Session() ethernet_session.mount("http://", SourceIPAdapter(ETHERNET_IP)) ethernet_session.mount("https://", SourceIPAdapter(ETHERNET_IP)) ethernet_response = ethernet_session.get("https://api.ipify.org") print(f"Ethernet request external IP: {ethernet_response.text}")
How It Works
We create a custom HTTPAdapter that tells urllib3 (the backend for requests) to bind outgoing connections to a specific source IP. Each session uses its own adapter, so requests from each session route through the specified interface.
C Implementation
For C, use libcurl (a robust HTTP client library) which supports directly specifying the network interface.
Example: Route Requests to Specific Interfaces with libcurl
#include <stdio.h> #include <curl/curl.h> // Callback to print response data size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; printf("Response: %.*s\n", (int)realsize, (char*)contents); return realsize; } int main(void) { CURL *curl_wifi, *curl_ethernet; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); // Request via Wi-Fi (replace "en0" with your Wi-Fi interface name) curl_wifi = curl_easy_init(); if(curl_wifi) { curl_easy_setopt(curl_wifi, CURLOPT_URL, "https://api.ipify.org"); curl_easy_setopt(curl_wifi, CURLOPT_INTERFACE, "en0"); // Bind to Wi-Fi curl_easy_setopt(curl_wifi, CURLOPT_WRITEFUNCTION, write_callback); res = curl_easy_perform(curl_wifi); if(res != CURLE_OK) fprintf(stderr, "Wi-Fi request failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl_wifi); } // Request via Ethernet (replace "en1" with your Ethernet interface name) curl_ethernet = curl_easy_init(); if(curl_ethernet) { curl_easy_setopt(curl_ethernet, CURLOPT_URL, "https://api.ipify.org"); curl_easy_setopt(curl_ethernet, CURLOPT_INTERFACE, "en1"); // Bind to Ethernet curl_easy_setopt(curl_ethernet, CURLOPT_WRITEFUNCTION, write_callback); res = curl_easy_perform(curl_ethernet); if(res != CURLE_OK) fprintf(stderr, "Ethernet request failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl_ethernet); } curl_global_cleanup(); return 0; }
Compile and Run
Compile with libcurl (install it via Homebrew if needed: brew install curl):
gcc -o interface_requests interface_requests.c -lcurl ./interface_requests
How It Works
The CURLOPT_INTERFACE option tells libcurl to use the specified interface for the connection. You can pass either the interface name (like en0) or its IP address.
Key Notes
- Interface Names: Double-check your interface names with
ifconfig—macOS usesen0for Wi-Fi on most laptops, but Ethernet can vary based on hardware. - HTTPS Support: Both examples work seamlessly with HTTPS, since the binding happens at the socket level (not the application layer).
- Permissions: No root/sudo is needed for most requests unless you’re binding to a privileged port (below 1024).
内容的提问来源于stack exchange,提问作者pippo

