C 如何查找连接的套接字使用的网络接口
如何找到连接的套接字使用的接口。这样我就可以为不同的接口设置状态代码。我使用了下面的代码。但是我没有得到它 我在下面的测试代码中尝试了两种不同的方法,但都失败了。第一个连接到远程服务器,并使用ioctl和SIOCGIFNAME,但由于“没有这样的设备”而失败。第二个使用getsockopt和SO_BINDTODEVICE,但再次失败(它将名称长度设置为0) 关于这些失败的原因,或者如何获得I/F名称,有什么想法吗?编译后,将测试代码作为测试“a.b.c.d”运行,其中a.b.c.d是侦听端口80的任何IPV4地址。请注意,我在Centos 7上编译了这个,它似乎没有IFNAMSZ,因此您可能需要注释掉#define IFNAMSZ行,以便在其他系统上编译 谢谢C 如何查找连接的套接字使用的网络接口,c,linux,sockets,networking,ioctl,C,Linux,Sockets,Networking,Ioctl,如何找到连接的套接字使用的接口。这样我就可以为不同的接口设置状态代码。我使用了下面的代码。但是我没有得到它 我在下面的测试代码中尝试了两种不同的方法,但都失败了。第一个连接到远程服务器,并使用ioctl和SIOCGIFNAME,但由于“没有这样的设备”而失败。第二个使用getsockopt和SO_BINDTODEVICE,但再次失败(它将名称长度设置为0) 关于这些失败的原因,或者如何获得I/F名称,有什么想法吗?编译后,将测试代码作为测试“a.b.c.d”运行,其中a.b.c.d是侦听端口80
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char **argv) {
int sock;
struct sockaddr_in dst_sin;
struct in_addr haddr;
if(argc != 2)
return 1;
if(inet_aton(argv[1], &haddr) == 0) {
printf("'%s' is not a valid IP address\n", argv[1]);
return 1;
}
dst_sin.sin_family = AF_INET;
dst_sin.sin_port = htons(80);
dst_sin.sin_addr = haddr;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
if(connect(sock, (struct sockaddr*)&dst_sin, sizeof(dst_sin)) < 0) {
perror("connect");
return 1;
}
printf("connected to %s:%d\n",
inet_ntoa(dst_sin.sin_addr), ntohs(dst_sin.sin_port));
#if 0 // ioctl fails with 'no such device'
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
// get the socket's interface index into ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
// get the I/F name for ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFNAME, &ifr) < 0) {
perror("SIOCGIFNAME");
return 1;
}
printf("I/F is on '%s'\n", ifr.ifr_name);
#else // only works on Linux 3.8+
#define IFNAMSZ IFNAMSIZ // Centos7 bug in if.h??
char optval[IFNAMSZ] = {0};
socklen_t optlen = IFNAMSZ;
if(getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &optval, &optlen) < 0) {
perror("getsockopt");
return 1;
}
if(!optlen) {
printf("invalid optlen\n");
return 1;
}
printf("I/F is on '%s'\n", optval);
#endif
close(sock);
return 0;
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
int袜子;
dst_sin中的结构sockaddr_;
地址haddr中的结构;
如果(argc!=2)
返回1;
if(inet_aton(argv[1],&haddr)==0){
printf(“%s”不是有效的IP地址\n”,argv[1]);
返回1;
}
dst_sin.sin_family=AF_INET;
dst_sin.sin_port=htons(80);
dst_sin.sin_addr=haddr;
if((sock=socket(AF_INET,sock_STREAM,0))<0){
佩罗(“插座”);
返回1;
}
if(connect(sock,(struct sockaddr*)和dst_sin,sizeof(dst_sin))<0){
perror(“连接”);
返回1;
}
printf(“已连接到%s:%d\n”,
inet_ntoa(dst_sin.sin_addr),ntohs(dst_sin.sin_port));
#如果0//ioctl因“无此类设备”而失败
结构ifreq-ifr;
memset(&ifr,0,sizeof(ifr));
//将套接字的接口索引获取到ifreq.ifr\u ifindex中
如果(ioctl(sock、SIOCGIFINDEX和ifr)<0){
perror(“SIOCGIFINDEX”);
返回1;
}
//获取ifreq.ifr\U ifindex的I/F名称
if(ioctl(sock、SIOCGIFNAME和ifr)<0){
佩罗(“SIOCGIFNAME”);
返回1;
}
printf(“I/F位于'%s'\n',ifr.ifr\u名称);
#else//仅适用于Linux 3.8+
#在if.h中定义IFNAMSZ IFNAMSIZ//Centos7错误??
char optval[IFNAMSZ]={0};
socklen_t optlen=国际消防安全公约;
if(getsockopt(sock、SOL_SOCKET、SO_BINDTODEVICE和optval及optlen)<0){
perror(“getsockopt”);
返回1;
}
如果(!optlen){
printf(“无效的optlen\n”);
返回1;
}
printf(“I/F位于“%s”\n”,optval);
#恩迪夫
关闭(袜子);
返回0;
#include <arpa/inet.h>
#include <assert.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
int sockfd=-1;
void connect2(const char *const dst){
sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd>=3);
struct sockaddr_in sin={
.sin_family=AF_INET,
.sin_port=htons(80),
.sin_addr={}
};
assert(1==inet_pton(AF_INET,dst,&(sin.sin_addr)));
assert(0==connect(sockfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in)));
}
void getsockname2(struct sockaddr_in *const sin){
socklen_t addrlen=sizeof(struct sockaddr_in);
assert(0==getsockname(sockfd,(struct sockaddr*)sin,&addrlen));
assert(addrlen==sizeof(struct sockaddr_in));
}
void disconnect(){
close(sockfd);
sockfd=-1;
}
void addr2iface_ifconf(const struct in_addr *const sin_addr,int *const index,char *const name){
struct ifconf ifc={
.ifc_len=0,
.ifc_req=NULL
};
int ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
assert(ioctlfd>=3);
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
const int sz=ifc.ifc_len;
assert(sz%sizeof(struct ifreq)==0);
const int n=sz/sizeof(struct ifreq);
char buf[sz];
bzero(buf,sz);
ifc.ifc_buf=buf;
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
assert(
ifc.ifc_len==sz &&
(char*)ifc.ifc_req==buf
);
for(int i=0;i<n;++i)if(0==memcmp(
&(((struct sockaddr_in*)(&(ifc.ifc_req[i].ifr_addr)))->sin_addr),
sin_addr,
sizeof(struct in_addr)
)){
*index=ifc.ifc_req[i].ifr_ifindex;
assert(name==strncpy(name,ifc.ifc_req[i].ifr_name,IFNAMSIZ));
return;
}
assert(0);
}
int main(int argc,const char *argv[]){
assert(argc==2);
assert(argv[1]&&strlen(argv[1]));
const char *const remoteaddr_s=argv[1];
// const char *const remoteaddr_s="93.184.216.34";
connect2(remoteaddr_s);
struct sockaddr_in ifaddr={};
getsockname2(&ifaddr);
disconnect();
int index=0;
char ifname[IFNAMSIZ]={};
addr2iface_ifconf(&(ifaddr.sin_addr),&index,ifname);
char ifaddr_s[INET_ADDRSTRLEN]={};
assert(ifaddr_s==inet_ntop(AF_INET,&(ifaddr.sin_addr),ifaddr_s,INET_ADDRSTRLEN));
printf("interface index : %d\n",index);
printf("interface name : %s\n",ifname);
printf("interface address : %s\n",ifaddr_s);
printf("remote address : %s\n",remoteaddr_s);
// printf("#%d %s %s -> %s\n",
// index,
// ifname,
// ifaddr_s,
// remoteaddr_s
// );
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int sockfd=-1;
无效连接2(常量字符*常量dst){
sockfd=套接字(AF_INET,SOCK_STREAM,0);
断言(sockfd>=3);
sin中的结构sockaddr_={
.sin_family=AF_INET,
.sin_port=htons(80),
.sinu addr={}
};
断言(1==inet\u pton(AF\u inet,dst,&(sin.sin\u addr));
断言(0==connect(sockfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in));
}
void getsockname2(结构sockaddr_in*const sin){
socklen\u t addrlen=sizeof(结构sockaddr\u in);
断言(0==getsockname(sockfd,(struct sockaddr*)sin,&addrlen));
断言(addrlen==sizeof(struct sockaddr_in));
}
无效断开连接(){
关闭(sockfd);
sockfd=-1;
}
void addr2iface\u ifconf(地址中的常量结构*常量sin\u addr,int*常量索引,字符*常量名称){
结构ifconf ifc={
.ifc_len=0,
.ifc_req=NULL
};
int ioctlfd=插座(AF INET、SOCK DGRAM、IPPROTO_UDP);
断言(ioctlfd>=3);
断言(0==ioctl(ioctlfd、SIOCGIFCONF和ifc));
const int sz=ifc.ifc_len;
断言(sz%sizeof(struct ifreq)==0);
const int n=sz/sizeof(struct ifreq);
char-buf[sz];
bzero(buf,sz);
ifc.ifc_buf=buf;
断言(0==ioctl(ioctlfd、SIOCGIFCONF和ifc));
断言(
ifc.ifc_len==sz&&
(char*)ifc.ifc_req==buf
);
对于(int i=0;isin_addr),
新地址:,
sizeof(地址中的结构)
)){
*索引=ifc.ifc需求[i].ifr\U ifindex;
assert(name==strncpy(name,ifc.ifc_-req[i].ifr_-name,IFNAMSIZ));
返回;
}
断言(0);
}
int main(int argc,const char*argv[]{
断言(argc==2);
断言(argv[1]&&strlen(argv[1]);
const char*const remoteaddr_s=argv[1];
//const char*const remoteaddr_s=“93.184.216.34”;
连接2(远程地址);
ifaddr={}中的结构sockaddr_;
getsockname2(&ifaddr);
断开连接();
int指数=0;
字符ifname[IFNAMSIZ]={};
addr2iface_ifconf(&(ifaddr.sin_addr),&index,ifname);
char ifaddr_s[INET_ADDRSTRLEN]={};
断言(ifaddr_s==inet_ntop(AF_inet,&(ifaddr.sin_addr),ifaddr_s,inet_ADDRSTRLEN));
printf(“接口索引:%d\n”,索引);
printf(“接口名称:%s\n”,ifname);
printf(“接口地址:%s\n”,ifaddr\u s);
printf(“远程地址:%s\n”,remoteaddr\s);
//printf(#%d%s%s->%s\n),
//索引,
//如果名称,
//IFADR_s,
//远程地址
// );
返回0;
}
还没有一个名为IFNAMSZ的标识符。IFNAMS <强> iZ定义为Maxim-LethH(包括“0”),允许任何接口IMHO。< /P> @ RahulChandran,您可能应该考虑点击投票按钮下方的刻度。
#include <arpa/inet.h>
#include <assert.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
int sockfd=-1;
void connect2(const char *const dst){
sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd>=3);
struct sockaddr_in sin={
.sin_family=AF_INET,
.sin_port=htons(80),
.sin_addr={}
};
assert(1==inet_pton(AF_INET,dst,&(sin.sin_addr)));
assert(0==connect(sockfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in)));
}
void getsockname2(struct sockaddr_in *const sin){
socklen_t addrlen=sizeof(struct sockaddr_in);
assert(0==getsockname(sockfd,(struct sockaddr*)sin,&addrlen));
assert(addrlen==sizeof(struct sockaddr_in));
}
void disconnect(){
close(sockfd);
sockfd=-1;
}
void addr2iface_ifconf(const struct in_addr *const sin_addr,int *const index,char *const name){
struct ifconf ifc={
.ifc_len=0,
.ifc_req=NULL
};
int ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
assert(ioctlfd>=3);
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
const int sz=ifc.ifc_len;
assert(sz%sizeof(struct ifreq)==0);
const int n=sz/sizeof(struct ifreq);
char buf[sz];
bzero(buf,sz);
ifc.ifc_buf=buf;
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
assert(
ifc.ifc_len==sz &&
(char*)ifc.ifc_req==buf
);
for(int i=0;i<n;++i)if(0==memcmp(
&(((struct sockaddr_in*)(&(ifc.ifc_req[i].ifr_addr)))->sin_addr),
sin_addr,
sizeof(struct in_addr)
)){
*index=ifc.ifc_req[i].ifr_ifindex;
assert(name==strncpy(name,ifc.ifc_req[i].ifr_name,IFNAMSIZ));
return;
}
assert(0);
}
int main(int argc,const char *argv[]){
assert(argc==2);
assert(argv[1]&&strlen(argv[1]));
const char *const remoteaddr_s=argv[1];
// const char *const remoteaddr_s="93.184.216.34";
connect2(remoteaddr_s);
struct sockaddr_in ifaddr={};
getsockname2(&ifaddr);
disconnect();
int index=0;
char ifname[IFNAMSIZ]={};
addr2iface_ifconf(&(ifaddr.sin_addr),&index,ifname);
char ifaddr_s[INET_ADDRSTRLEN]={};
assert(ifaddr_s==inet_ntop(AF_INET,&(ifaddr.sin_addr),ifaddr_s,INET_ADDRSTRLEN));
printf("interface index : %d\n",index);
printf("interface name : %s\n",ifname);
printf("interface address : %s\n",ifaddr_s);
printf("remote address : %s\n",remoteaddr_s);
// printf("#%d %s %s -> %s\n",
// index,
// ifname,
// ifaddr_s,
// remoteaddr_s
// );
return 0;
}