10

私は2つのプログラムを持っています:

  • サーバー ... 選択したマルチキャストで UDP トラフィックを生成します
  • リスナー ... 選択したマルチキャストで UDP トラフィックを出力します (マルチキャストにサブスクライブし、受信したものを出力します)。

あるマシンでサーバーを実行し、いくつかの (他の) マシンでリスナーを実行すると、リスナーは UDP トラフィックを認識し、正しく出力します。したがって、これらのプログラムは良好な状態にあるはずです。

ただし、どのマシンでも、tcpdump を使用してトラフィックをキャプチャしようとすると、次のようになります。

sudo tcpdump -i eth0 'dst 233.65.120.153' -w 0.pcap

後で、どのマシンでも tcpreplay を使用して再生しようとすると、次のようになります。

sudo tcpreplay -i eth0 0.pcap

これらのキャプチャされたパケットは、どのリスナーにも表示されません。

09:38:40.975604 IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 32)
    172.27.6.176.53507 > 233.65.120.153.64968: [udp sum ok] UDP, length 4
    0x0000:  4500 0020 0000 4000 0111 6527 ac1b 06b0  E.....@...e'....
    0x0010:  e941 7899 d103 fdc8 000c 579c 6162 6364  .Ax.......W.abcd
    0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............
09:38:41.975709 IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 32)
    172.27.6.176.53507 > 233.65.120.153.64968: [udp sum ok] UDP, length 4
    0x0000:  4500 0020 0000 4000 0111 6527 ac1b 06b0  E.....@...e'....
    0x0010:  e941 7899 d103 fdc8 000c 579c 6162 6364  .Ax.......W.abcd
    0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............
09:38:42.975810 IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 32)
    172.27.6.176.53507 > 233.65.120.153.64968: [udp sum ok] UDP, length 4
    0x0000:  4500 0020 0000 4000 0111 6527 ac1b 06b0  E.....@...e'....
    0x0010:  e941 7899 d103 fdc8 000c 579c 6162 6364  .Ax.......W.abcd
    0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............

どのリスナーも UDP マルチキャスト トラフィックを認識していませんが、どのマシンでも tcpdump を使用してトラフィックを認識できることに注意してください。

sudo tcpdump -i eth0 'dst 233.65.120.153' -X

私の質問:作成中の UDP マルチキャスト トラフィックを tcpreplay して、tcpdump だけでなく、アプリケーション レベル (たとえば、リスナー プログラム) で確認したい場合は、どうすればよいですか?

$ 猫の送信者.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define PORT 64968
#define GROUP "233.65.120.153"

main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, cnt;
     struct ip_mreq mreq;
     char *message="abcd";

     /* Create what looks like an ordinary UDP socket:
        AF_INET    ... IPv4
        SOCK_DGRAM ... UDP
        0          ... required constant
      */
     if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
      perror("socket");
      exit(1);
     }

    /* Set up destination address:
        AF_INET ... IPv4
        GROUP   ... the IP-address of the multicast group
                    to which we want to multicast
        PORT    ... the UDP port that on which we want to multicast
      */
     memset(&addr, 0, sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=inet_addr(GROUP);
     addr.sin_port=htons(PORT);

     /* now just sendto() our destination! */
     while (1) {
      if (sendto(fd, message, strlen(message), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
           perror("sendto");
           exit(1);
      }
      sleep(1);
     }
}

$ 猫リスナー.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define PORT 64968
#define GROUP "233.65.120.153"
#define MSGBUFSIZE 1000000

char msgbuf[MSGBUFSIZE];

main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, nbytes,addrlen;
     struct ip_mreq mreq;

     u_int yes=1;

    /* Create what looks like an ordinary UDP socket:
       AF_INET ... IPv4
       SOCK_DGRAM ... UDP
       0 ... required constant
      */
    if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         perror("socket");
         exit(1);
    }

    /* Allow multiple sockets to use the same PORT number:
       SOL_SOCKET ... manipulate properties of the socket API itself
       SO_REUSEADDR ... Allow reuse of local addresses for bind
     */
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
       perror("Reusing ADDR failed");
       exit(1);
       }

     /* set up destination address */
     memset(&addr,0,sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
     addr.sin_port=htons(PORT);

     /* bind to receive address */
     if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
      perror("bind");
      exit(1);
     }

     /* use setsockopt() to request that the kernel join a multicast group */
     mreq.imr_multiaddr.s_addr=inet_addr(GROUP);
     mreq.imr_interface.s_addr=htonl(INADDR_ANY);
     if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
      perror("setsockopt");
      exit(1);
     }

     /* now just enter a read-print loop */
     while (1) {
      addrlen=sizeof(addr);
      memset(msgbuf, 0, MSGBUFSIZE);
      if ((nbytes=recvfrom(fd, msgbuf, MSGBUFSIZE,0,
                           (struct sockaddr *) &addr, &addrlen)) < 0) {
           perror("recvfrom");
           exit(1);
      }
      printf("Incoming message size = %d\n", nbytes);
      int i;
      for (i=0; i < nbytes; i++)
              printf("%02x ", ((unsigned char) msgbuf[i]));
      printf("\n");
     }
}
4

5 に答える 5

8

同じ問題がありました。tcpdump私たちはデータを見ました。ただし、マルチキャスト クライアント/リスナーはデータを取得していませんでした。次に、Reverse Path Filter (rp_filter) がパケットを拒否していることに気付きました。

rp-filter を無効にした後、クライアント/リスナー アプリケーションがパケットのピックアップを開始しました。次のコマンドを使用して、rp_filter を無効にします。

echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter

上記の「eth0」は、eth0 以外の場合、マルチキャストを受信するインターフェイスに置き換えます。

于 2014-03-26T07:40:52.480 に答える
2

私の場合、正しい宛先 MAC アドレスを設定して pcap ファイルを調整する必要がありました。チェックサムも再計算する必要があります。はい、「tcpreplay」には 2 つのホストが必要です。これらがなければ、私は長い間戦っていましたが、マルチキャストリスニングアプリではなく、「tcpdump」だけが再生されたストリームを示しました:(

ここに私の記事へのリンクがあります: Dump/Replay Multicast feed の段階的な説明

于 2015-09-11T22:46:18.397 に答える
1

これはあくまで理論上の話ですが、チェックサムが間違っているために受信側でパケットが破棄されている可能性があります。

これは、tcpdump を実行するマシンで IP または UDP チェックサムのオフロードが有効になっている場合に発生する可能性があります。つまり、ローカルでキャプチャしたパッケージは、チェックサムがまだ計算されていないことを意味します。これは、ハードウェアがパッケージを送信する前に実行します。次にこれらのパケットを tcpreplay すると、チェックサムは計算されません。これは、tcpreplay がパケットの生成に使用したソケット API よりも低いレベルで動作するためです。

チェックサム (ダンプ ファイルのチェックサムと、後続の tcpreplay によって吐き出されたパケットのチェックサムの両方) の正確性を検証するために、tcpdump -v ...間違ったチェックサムについて警告が表示されます。また、wireshark は、間違ったチェックサム フレームの色を別の色に変更します (wireshark 設定でオフにしない限り)。

パケットの tcpdump を送信側ホストだけで試みましたか、それとも受信側ホストでも試みましたか? それが実際に問題である場合、後者はチェックサムエラーを削除します。

于 2015-12-22T01:00:26.837 に答える
1

私の知る限り、同じボックスでこれを行うことはできません。tcpreplay はホストのルーティング テーブルをバイパス、インターフェイスからトラフィックを送信します。

別のボックスでリスナーを開始する必要があります。マルチキャストが有効になっていることを確認します。デフォルトでは、スイッチはマルチキャスト トラフィックを破棄するためです。

于 2012-11-29T07:08:54.357 に答える