Ethernetインターフェースを指定してソケットを作成する (Raspberry Pi)

Raspberry Pi(Linux)で、C言語でEthernetインターフェースを使ってソケット通信する方法

Kauzmichi Shirai

Ethernetのソケット作成

LinuxでEthernetインターフェースを使ってソケット通信する場合、以下のようなコードを書くことでソケット通信の準備ができる.

    deststr = IP_ADDRESS; //接続先のIPアドレス #define IP_ADRESS ("192.168.0.12")
     /* ソケットを生成 */
     if((*sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
     {
          printf("fail to create socket\n");
          return -1;
     }

     /* 接続先サーバのアドレス構造体の作成 */
     memset(&server, 0, sizeof(server));
     server.sin_family = PF_INET;
     server.sin_addr.s_addr = inet_addr(deststr);
     server.sin_port = htons(PORT);

     /* 接続処理 */
     if(connect (*sock, (struct sockaddr *)&server, sizeof(server)) < 0)
     {
          printf("fail to connect\n");
          return -1;
     }

ただ、このコードだと、複数のEthernetインターフェースある場合、自動で1つのEthernetインターフェースが使われることになる.
例えば、”eth0”, “eth1”と二つのEthernetインターフェースがあったとき、自動で”eth0”のインターフェースを使ったsokcetが作成される.

“eth1”のsokectを作成したい

ここで、”eth1”のインターフェースを使ったsokcet通信がしたい場合は、setsockopt関数でインターフェースを指定してやればいい.setsockopt()はソケットの生成socket()と接続処理connect()の間で呼び出す.

    deststr = IP_ADDRESS; //Set IP address
     /* ソケットを生成 */
     if((*sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
     {
          printf("fail to create socket\n");
          return -1;
     }

     /** For usb-ehternet converter **/
     char *opt;
     opt = "eth1";
     setsockopt(*sock, SOL_SOCKET, SO_BINDTODEVICE, opt, 4);

     /* 接続先サーバのアドレス構造体の作成 */
     memset(&server, 0, sizeof(server));
     server.sin_family = PF_INET;
     server.sin_addr.s_addr = inet_addr(deststr);
     server.sin_port = htons(PORT);

     /* 接続処理 */
     if(connect (*sock, (struct sockaddr *)&server, sizeof(server)) < 0)
     {
          printf("fail to connect\n");
          return -1;
     }

参考 : http://stackoverflow.com/questions/3998569/how-to-bind-raw-socket-to-specific-interface

ルートで実行しないとダメ

しかし、上記のコードでも”eth1”のインターフェースで通信できなかった. 参考に挙げたぺーたをよくよく読んでみると、

SO_BINDTODEVICE only works if you run as root, right? (on Linux at least) –  sep332 Nov 27 '12 at 21:29

とコメントされている. つまりroot権限で実行しないといけないようだ. sudoで実行することで、無事に”eth1”のインターフェースで通信できるようになった.