• ベストアンサー

Linuxでパケットを発信する際・・・。

ひとつ疑問なのですが、たとえばudpでパケットを送信するときに、sockaddr構造体を使って dest_addr.sin_port = htons(10001); などで送信先を定義しますよね。このとき、自分の発信元ポートは 決められないのでしょうか。 通信相手がマイコンでして、要求パケットを受けたら自分のステータスを 発信元にそのまま送り返すというシロモノで・・・発信元ポートがわからないと サーバ側でlistenできないんです・・・。 パケットを拾ったところ、1045発10001着のようにランダムで決められているんですね。 なにかいいアイデアはありますでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.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;

pythian
質問者

お礼

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

pythian
質問者

補足

わざわざありがとうございます。 自分の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なのでポートが同じなのは問題ありません) 自分で解釈しながらカスタマイズしてしまったのですが・・・試行錯誤してもわかりませんでした。お手数をおかけしてすみません。

その他の回答 (3)

  • Fooky
  • ベストアンサー率71% (59/82)
回答No.3

発信元で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台)

pythian
質問者

お礼

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

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.2

> bindしてみたところ、sendtoしても全くパケットが出なくなってしまいました ポート番号だけじゃなくて、相手先のIPアドレスもきちんと設定しましたよね? # 思い付きで振り回すのも、アレなんですが… (^^;

pythian
質問者

補足

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

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

> このとき、自分の発信元ポートは決められないのでしょうか。 普通 UDP で送信 sendto() するときには、bind() はしなくても良いのですが、 bind() してから、sendto() してみてはどうでしょうか? # ちょっと思い付いただけで、試してみてません

pythian
質問者

補足

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

関連するQ&A

  • objective-c iphoneからUDP送信

    iphoneからUDPで192.168.0.3、3054ポートに0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x44, 0x33, 0x05の13バイトのバイナリデータを送信したいのですが、以下のソースで実行可能でしょうか?ご教授お願いします。 #import <CoreFoundation/CoreFoundation.h> #import <sys/socket.h> #import <netinet/in.h> CFSocketRef socket = CFSocketCreate(NULL, PF_INET, SOCK_DGRAM, IPPROTO_UDP, kCFSocketNoCallBack, NULL, NULL); struct sockaddr_in addr; addr.sin_len = sizeof(struct sockaddr_in); addr.sin_family = AF_INET; addr.sin_addr.s_addr = addr.sin_addr.s_addr = inet_addr(”192.168.0.3); addr.sin_port = htons(3054); CFDataRef address = CFDataCreate(NULL, (UInt8*)&addr, sizeof(struct sockaddr_in)); char* message = "\x42\42\0\0\0\0\2\0\1\2\x44\x33\5"; CFDataRef data = CFDataCreate(NULL, (UInt8*)message, strlen(message)); CFSocketSendData(socket, address, data, 3); CFRelease(socket); CFRelease(address); CFRelease(data); char*messageはおかしいですかね…。宜しくお願いします。

  • UDP通信について

    UDP通信で困っています。 TCP/IP通信はすぐにうまくいったのですが、 UDPの簡単なサンプルがちゃんと動きません。 間違いがあればご指摘ください。 よろしくお願いします。 (クライアント側ソース int sock; struct sockaddr_in din; memset(&din, 0, sizeof(din)); din.sin_port = htons(50050); din.sin_family = AF_INET; din.sin_addr.s_addr = inet_addr("サーバーIP"); sock = socket(AF_INET, SOCK_DGRAM, 0); int buf = 12345; sendto(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&din,sizeof(struct sockaddr_in)); (サーバー側ソース int sock; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(50050); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { return(1); } struct sockaddr_in fromaddr; socklen_t len = sizeof(struct sockaddr_in); int buf; recvfrom(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&fromaddr,&len); printf("recv:%d\n",buf);

  • Cプログラム UDP送信の送信データに関して

    以下の2つのプログラムでの質問なのですが、 #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2, 0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3 "); sendto(sock, "\x42\42\0\0\0\0\2\0\1\2\x44\x33\5", 13, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } と #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2, 0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3 "); sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } について、送信データ部分に「¥」入ることによって、送信プロセスでどのような処理がなされているのですか? ¥~¥までで1バイトということで処理してくださいね、と処理系?に指示しているのですか? また、「¥」はC言語ならではの表記の仕方なのですか?少し、伝えるのが難しいですが、何でもいいのでご回答頂けませんか?宜しくお願いします。

  • セグメンテーション違反

    C言語でネットワークを流れるパケットの取得&解析を行っているのですが、実行時にセグメンテーション違反と出てしまい、困っています。デバッグオプションをつけてやってみたところ、プログラムが中断されたところは分かったのですが、どこが悪いのか分かりません。どなたかあやしいところがありましたらお教え下さい。 OSはLinuxでコンパイラはgccです。 void udp_scanport(struct ip *ip, struct udphdr *udp) { static struct in_addr *ipaddr[1024]; static int i = -1; static int udp_count[1024]; struct in_addr *inwk; static u_short udp_port[1024]; int u = 0; int k = 0; i++; inwk = (struct in_addr *)malloc(sizeof(struct in_addr)); memcpy(inwk, &ip->ip_src, sizeof(struct in_addr)); ipaddr[i] = (struct in_addr *)inwk; printf("送信元IPアドレス:%15s\n", inet_ntoa(*(struct in_addr *) ipaddr[i])); udp_port[i] = udp->uh_dport; /*デバッグしたら中断したところ*/ printf("UDP送信先ポート番号:%15u\n", ntohs(udp_port[i])); if (i == 100) free(inwk); }

  • UDPでのブロードキャスト送信

    Linuxで下記UDPブロードキャスト送信プログラムを作ったのですが、sendto()関数の戻り値が-1となり エラーとなってしまうので送信できません。 何が悪いのでしょうか? ちなみにIPアドレスは192.168.0.1 サブネットマスクは255.255.0..0でやっています。 又、サブネットマスクを0.0.0.0で試してもみましたがダメでした。 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> int main() { int sock; struct sockaddr_in addr; int yes = 1; sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.s_addr = inet_addr("255.255.255.255"); setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes)); if(sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr))!=5) printf("send error!!\n"); close(sock); return 0; }

  • SOCKETのUDPについて

    こんにちは。 SOCKETのUDPに使って通信をしようと思っています。 UDPは到達保証はされないとありますが、sendto関数で送信した内容のそのものも保証されないのでしょうか? sendto(sock, "HogeHoge", 8, 0, (struct sockaddr *)&addr, sizeof(addr)); とした場合、"HogeH"となったり"HHooggee"となったりするのでしょうか?

  • ソケットを使ったプログラムにおいて

    こんにちは。 winsockを使って、2PC間での通信を行いたいのですが、sockaddr_in構造体は struct sockaddr_in echoServAddr; echoServAddr.sin_family = AF_INET; echoServAddr.sin_addr.s_addr = inet_addr(servIP); echoServAddr.sin_port = htons(echoServPort); と表記されると思いますが、2PCをクロスケーブルでつないで相手を認識したい場合、servIPの値はどうなりますか? ご教授下さい。 環境: VC++ 6.0(SP5)

  • socket通信でのフィルタリング

    linux環境にてC言語でUDPソケットのプログラムを作成しています。 Aの端末からUDPで受信してパケットヘッダの表示及び、宛先アドレスや宛先ポート番号 を書き換えてBの端末にUDPで送信します。 そこで下記の関数を使用して受信しているのですが、パケットキャプチャのように なんでも受信してしまいます。 socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) これを特定のポート番号だけ受信(フィルタ)するにはどのようにすれば良いのでしょうか?

  • winsockを使った通信方法

    送信側 #include <winsock2.h> #include <string.h> int main() { WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; typedef struct recv { char Name[32]; int Flag; } RECV; RECV send; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); strcat(send.Name, "ABC"); send.Flag=12; len=sizeof(send); sendto(sock,(char *)&send,len, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); system("pause"); return 0; } 受信側 #include <stdio.h> #include <winsock2.h> #include <string.h> int main() { typedef struct rcv { char Name[32]; int Flag; } RECV; WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; RECV rcv; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); len=sizeof(rcv); recv(sock,(char *)&rcv, len, 0); printf("%s [%d]\n",rcv.Name,rcv.Flag); closesocket(sock); WSACleanup(); system("pause"); return 0; } winsockを使ったUDP通信プログラムで構造体データを送る事が出来ないのですが どこに誤りがあるのでしょうか? コンパイルは通ってるのですが、送信側を起動しても受信側で受け取ることが出来ていない状況です。

  • 不明なIPアドレスから外部に発信する

    設定した覚えのないIPアドレスから外部に発信するようになり、セキュリティソフトから、外部への発信をブロックしたとのメッセージが1時間に数件表示されるようになった。 ちなみに、ネットワークから離してPINGしてもREPLYがあります。 セキュリティソフトの履歴には次のように記録されています。 ユーザ:SYSTEM 方向:送信 アクセス:拒否 プロトコル:UDP(17) 発信元IP:169.254.64.20 リモートIP:169.254.255.255 発信元ポート:137 リモートポート:137