- ベストアンサー
Linuxでパケットを発信する際・・・。
ひとつ疑問なのですが、たとえばudpでパケットを送信するときに、sockaddr構造体を使って dest_addr.sin_port = htons(10001); などで送信先を定義しますよね。このとき、自分の発信元ポートは 決められないのでしょうか。 通信相手がマイコンでして、要求パケットを受けたら自分のステータスを 発信元にそのまま送り返すというシロモノで・・・発信元ポートがわからないと サーバ側でlistenできないんです・・・。 パケットを拾ったところ、1045発10001着のようにランダムで決められているんですね。 なにかいいアイデアはありますでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
少し時間が取れたので、私も試してみました。 a-kuma> ポート番号だけじゃなくて、相手先のIPアドレスもきちんと設定しましたよね? 何を言ってるんでしょうね。思い付きの方は良かったのに、頭の中が腐ってる ようです (^^; No.3 の Fooky さんも「さっきやった間違い」とあるので、私だけが特に そこつ者 なわけではないようですが、思い込みがあったので、ちょっとはまりました。 ■送信側 int sock = socket(PF_INET, SOCK_DGRAM, 0); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(2500); // このポートに返して欲しい addr.sin_addr.s_addr = INADDR_ANY; bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in)); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(1999); // 送信の為のポート memcpy(&addr.sin_addr.s_addr, gethostbyname("相手のホスト名")->h_addr_list[0], sizeof(addr.sin_addr.s_addr)); char* buf = "test message"; sendto(sock, buf, strlen(buf) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr_in)); ■受信側 int sock = socket(PF_INET, SOCK_DGRAM, 0); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(1999); addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in)); char buf[256]; int len; recvfrom(sock, buf, sizeof(buf), 0, (sockaddr*)&addr, &len); cout << "port: " << htons(addr.sin_port) << endl;
その他の回答 (3)
- Fooky
- ベストアンサー率71% (59/82)
発信元でbind()して出来ませんか? 手元のプログラムをちょっと変えて 実験してみたら問題なくできましたよ。 ・発信元ソケットにbindするポート番号は 1025以上を使っているか? => bind()でPermission denied 1024以下なら、スーパーユーザにならない とダメ ・他のプロセスが既に使っているポート番号を 使っていないか?=> bind()でAddress already in use あと、私がさっきやった間違いなんですが、 ・bind()に渡すsockaddr構造体の値を代入する際に、 sendto()に渡すsockaddr構造体への代入を真似て 書きませんでしたか?=> sendto()でInvalid argument bind()に渡す分をsockaddr_in srcadr;とし、 sendto()に渡す分をsockaddr_in dstadr;とすると、 srcadrの方は、sin_addr.s_addrにINADDR_ANYをセットし、 dstadrのsin_addrメンバには、gethostbyname()で取得した hostent構造体のh_addr_list[0]の中身をコピーする。 私がさっき実験したときに気付いたのはこの程度です。 とにかく、方法としてはa-kumaさんが指摘された 方法で行けるようですよ。 (実験環境Linux-2.2.14 × 2台)
お礼
ありがとうございます、なんとか解決しました。 bindできないと叫んでいたのは、どうもポートがだぶっていてaddress already in useで失敗していたようです。エラー処理をつけたら簡単に見つかりました(おバカです・・・) どうもありがとうございました。
- a-kuma
- ベストアンサー率50% (1122/2211)
> bindしてみたところ、sendtoしても全くパケットが出なくなってしまいました ポート番号だけじゃなくて、相手先のIPアドレスもきちんと設定しましたよね? # 思い付きで振り回すのも、アレなんですが… (^^;
補足
はい。とりあえず、ソケット生成後の sockaddr.sin_family sockaddr.sin_port sockaddr.sin_addr.s_addr の3つは設定してあります。 思いつきだなんてとんでもない、ありがとうございます(^^;;
- a-kuma
- ベストアンサー率50% (1122/2211)
> このとき、自分の発信元ポートは決められないのでしょうか。 普通 UDP で送信 sendto() するときには、bind() はしなくても良いのですが、 bind() してから、sendto() してみてはどうでしょうか? # ちょっと思い付いただけで、試してみてません
補足
パケットのモニタリングをしながらやってみたのですが、bindしてみたところ、sendtoしても全くパケットが出なくなってしまいました・・・。難しいですね...(^_^;
お礼
なんとか解決しました。 どうも、ポートがだぶっていてbind()で失敗していたようです。エラー処理をつけたらあっさりと原因がわかりました(^^; ありがとうございました。
補足
わざわざありがとうございます。 自分のsockaddrをbindして、相手のaddrでsendtoするということですね。 ということは、ソケット転送のプログラムなので、 //////////////////////////////////// udp_socket = socket(AF_INET, SOCK_DGRAM,0); memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.sin_port = htons(10001); bind(udp_socket, (struct sockaddr *) &my_addr, sizeof(my_addr)); // クライアントからポート10001でデータを受信する //////////////////////////////////// //////////////////////////////////// udp_socket2 = socket(AF_INET,SOCK_DGRAM,0); bind(udp_socket2, (struct sockaddr*)&my_addr, sizeof(my_addr)); memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = inet_addr("192.168.253.1") ; dest_addr.sin_port = htons(10001); // 192.168.253.1のポート10001へデータを送信する //////////////////////////////////// という形でいいのでしょうか?(長くてすみません・・・) 実は、これで試したところ再度1051番辺りからパケットが出てしまいまして・・・。 (ダブルNICなのでポートが同じなのは問題ありません) 自分で解釈しながらカスタマイズしてしまったのですが・・・試行錯誤してもわかりませんでした。お手数をおかけしてすみません。