要指定建立連線的網路介面,只要使用 bind 函數,指定對應的網路介面即可。在 iOS 中選擇 WIFI 或是 3G 也是同樣的道理,以iPhone為例,其網路介面名稱定義如下
- WIFI 為 en0
- 3G 為 pdp_ip0。
這裡提供一個簡單的程式範例,可以列出設備上所有的網路卡介面,建立 socket 並綁定到對應的網路介面,接著使用者只要使用此 socket 傳送資料,便可以透過指定的網路介面傳送出去了。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #include <time.h> #include <errno.h> #include <stdarg.h> #include <ifaddrs.h> // getifaddrs() #include <sys/ioctl.h> // struct ifreq #define INTERFACE_WIFI "en" // en0 #define INTERFACE_WWAN "pdp_ip" // pdp_ip0 typedef enum { eStunNIC_WIFI, eStunNIC_WWAN //GPRS, EDGE, 3G }eStunNIC; int GetNICAddr(eStunNIC veStunNIC, struct sockaddr_in *pSockAddr_In); main() { int sock; struct sockaddr_in client; bzero(&client, sizeof(client)); // List all NIC, and select WIFI or 3G NIC res = GetNICAddr(eStunNIC_WIFI, &client); if( res < 0 ) { printf( "GetNICAddr Fail\n"); return 0; } sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if( sock < 0 ) { printf( "Error creating socket\n"); return 0; } // Bind the socket to interface WIFI or 3G if (bind(sock, (struct sockaddr*)&client, sizeof(client)) < 0) { printf("bind fail\n"); close(sock); } else { printf( "bind success\n"); } return 0; } int GetNICAddr(eStunNIC veStunNIC, struct sockaddr_in *pSockAddr_In) { int result=0; char *pNIC=NULL; struct ifaddrs * ifAddrStruct=NULL; struct ifaddrs * ifa=NULL; void * tmpAddrPtr=NULL; if(veStunNIC==eStunNIC_WIFI) pNIC = INTERFACE_WIFI; else if(veStunNIC==eStunNIC_WWAN) pNIC = INTERFACE_WWAN; else return -1; result = getifaddrs(&ifAddrStruct); if(result!=0) { printf("getifaddrs error!!\n"); return -1; } printf("List all network interface of this machine!!\n"); for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 // is a valid IP4 Address char addressBuffer[INET_ADDRSTRLEN]; tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); printf("\tNIC name:%s, IP Address %s\n", ifa->ifa_name, addressBuffer); // Assume only one WIFI interface and only one 3G interface if(strncmp(ifa->ifa_name, pNIC, strlen(pNIC))==0) { memcpy(pSockAddr_In, ((struct sockaddr_in *)ifa->ifa_addr), sizeof(struct sockaddr_in)); } } else if (ifa->ifa_addr->sa_family==AF_INET6) { tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; char addressBuffer[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); printf("\tNIC name:%s, IP Address %s\n", ifa->ifa_name, addressBuffer); } } if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct); if(veStunNIC==eStunNIC_WIFI) { printf("The address of WIFI NIC is %s\n\n", inet_ntoa(pSockAddr_In-> sin_addr)); } else if(veStunNIC==eStunNIC_WWAN) { printf("The address of WWAN NIC is %s\n\n", inet_ntoa(pSockAddr_In-> sin_addr)); } return 0; }