Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何查找连接的套接字使用的网络接口_C_Linux_Sockets_Networking_Ioctl - Fatal编程技术网

C 如何查找连接的套接字使用的网络接口

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

如何找到连接的套接字使用的接口。这样我就可以为不同的接口设置状态代码。我使用了下面的代码。但是我没有得到它

我在下面的测试代码中尝试了两种不同的方法,但都失败了。第一个连接到远程服务器,并使用ioctl和SIOCGIFNAME,但由于“没有这样的设备”而失败。第二个使用getsockopt和SO_BINDTODEVICE,但再次失败(它将名称长度设置为0)

关于这些失败的原因,或者如何获得I/F名称,有什么想法吗?编译后,将测试代码作为测试“a.b.c.d”运行,其中a.b.c.d是侦听端口80的任何IPV4地址。请注意,我在Centos 7上编译了这个,它似乎没有IFNAMSZ,因此您可能需要注释掉#define IFNAMSZ行,以便在其他系统上编译

谢谢

          #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;

  • 创建套接字
  • 连接
  • 获取接口地址
  • 从接口地址获取接口id和名称
  • 苏鲁克,63899229.c

    #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;
    
    }