アプリ版:「スタンプのみでお礼する」機能のリリースについて

ひとつ疑問なのですが、たとえばudpでパケットを送信するときに、sockaddr構造体を使って

dest_addr.sin_port = htons(10001);

などで送信先を定義しますよね。このとき、自分の発信元ポートは
決められないのでしょうか。

通信相手がマイコンでして、要求パケットを受けたら自分のステータスを
発信元にそのまま送り返すというシロモノで・・・発信元ポートがわからないと
サーバ側でlistenできないんです・・・。

パケットを拾ったところ、1045発10001着のようにランダムで決められているんですね。
なにかいいアイデアはありますでしょうか?

A 回答 (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;

この回答への補足

わざわざありがとうございます。
自分の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なのでポートが同じなのは問題ありません)

自分で解釈しながらカスタマイズしてしまったのですが・・・試行錯誤してもわかりませんでした。お手数をおかけしてすみません。

補足日時:2001/07/11 13:59
    • good
    • 0
この回答へのお礼

なんとか解決しました。
どうも、ポートがだぶっていてbind()で失敗していたようです。エラー処理をつけたらあっさりと原因がわかりました(^^;
ありがとうございました。

お礼日時:2001/07/13 14:08

発信元で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台)
    • good
    • 0
この回答へのお礼

ありがとうございます、なんとか解決しました。
bindできないと叫んでいたのは、どうもポートがだぶっていてaddress already in useで失敗していたようです。エラー処理をつけたら簡単に見つかりました(おバカです・・・)
どうもありがとうございました。

お礼日時:2001/07/13 14:09

> bindしてみたところ、sendtoしても全くパケットが出なくなってしまいました



ポート番号だけじゃなくて、相手先のIPアドレスもきちんと設定しましたよね?

# 思い付きで振り回すのも、アレなんですが… (^^;

この回答への補足

はい。とりあえず、ソケット生成後の
sockaddr.sin_family
sockaddr.sin_port
sockaddr.sin_addr.s_addr
の3つは設定してあります。
思いつきだなんてとんでもない、ありがとうございます(^^;;

補足日時:2001/07/09 17:27
    • good
    • 0

> このとき、自分の発信元ポートは決められないのでしょうか。



普通 UDP で送信 sendto() するときには、bind() はしなくても良いのですが、
bind() してから、sendto() してみてはどうでしょうか?

# ちょっと思い付いただけで、試してみてません

この回答への補足

パケットのモニタリングをしながらやってみたのですが、bindしてみたところ、sendtoしても全くパケットが出なくなってしまいました・・・。難しいですね...(^_^;

補足日時:2001/07/09 15:57
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!