#背景
Raspberry Pi+C言語で、2つのEthernetインターフェースで通信したいことがあり、その時に学んだことのメモです。
Ethernetのソケットの作成方法と、Ethernetのソケットの指定方法を記載します。
以下の環境で動作確認しました。
[ハードウェア]Raspberry Pi2 Model B
[OS]Raspbian GNU/Linux8.0(jessie)
#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"のインターフェースで通信できませんでした.
参考に挙げたweb pageをよくよく読んでみると、
SO_BINDTODEVICE only works if you run as root, right? (on Linux at least) – sep332 Nov 27 '12 at 21:29
とコメントされている.
つまりroot権限で実行しないといけないようです.
sudoで実行することで、無事に"eth1"のインターフェースで通信できるようになりました.