2012-05-05 12 views
0

私は、この奇妙な問題に取り組んでいます。recvfromは、255.255.255.255の宛先アドレスを持つブロードキャストパケットをキャッチしたときにのみ戻ります。クライアントに直接宛てられたパケット(つまり、クライアントIPを使用するパケット)は無視されます。recvfromは、255.255.255.255に送信されたパケットのみをキャッチします。

背景(これをスキップすることができます、私は何をしようとしているのかを明確にすることです) - 私は単純なBOOTPクライアントを実装しようとしています。私はBOOTREQUESTを作成することができ、サーバは正しいBOOTREPLY(wiresharkとlibpcapを使って書いた簡単なアナライザでチェックされています)で返信します。しかし、私はwiresharkで返信を見ても、クライアントのIPアドレスを宛先として使用するため、クライアントで受信できません。

私は他のコンピュータからもBOOTPパケットを受信できるネットワーク上でこれを試しています。私は、recvfromがブロードキャストアドレスを持つBOOTREPLYパケットを受信できることを知りました。悪い点は、サーバーが応答にユニキャストを使用できるようにするため、これらが私のものではないということです。

私が使用するコード:

sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
if (sockfd < 0) { 
    std::cerr << "Cannot create socket" << std::endl; 
    return; 
} 

int broadcastON = 1; 
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastON, sizeof(broadcastON)); 

sockaddr_in recv_address; 
memset((char *) &recv_address, 0, sizeof(recv_address)); 
recv_address.sin_family = AF_INET; 
recv_address.sin_port = htons(68); 
recv_address.sin_addr.s_addr = htonl(INADDR_ANY); 
int recv_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
if (recv_sockfd < 0) 
{ 
    std::cerr << "Cannot create socket" << std::endl; 
    return; 
} 
if (bind(recv_sockfd, (sockaddr *) &recv_address, sizeof(recv_address)) < 0) 
{ 
    std::cerr << "Cannot bind socket" << std::endl; 
    perror("bind"); 
    return; 
} 

sniff_bootp packet = createBootpPacket(mac); 
sockaddr_in server_address; 
memset((char *) &server_address, 0, sizeof(server_address)); 
server_address.sin_family = AF_INET; 
server_address.sin_port = htons(67); 
server_address.sin_addr.s_addr = htonl(INADDR_BROADCAST); 
if (sendto(sockfd, &packet, sizeof(packet),0,(sockaddr *) &server_address, sizeof(server_address)) < 0) 
{ 
    perror("sendto"); 
    return; 
} 
char msg[512]; 
while(1) 
{ 
    sockaddr_in source_address; 
    unsigned int cli_addr_len = sizeof(source_address); 
    // HERE IS THE PROBLEM 
    // returns only if the destination is broadcast 
    int msg_length = recvfrom(recv_sockfd, msg, 512, 0, (sockaddr *) &source_address, &cli_addr_len); 
    if (msg_length < 0) { 
     perror("rcvfrom"); 
     continue; 
    } 
+0

ファイアウォールはブロードキャストを除いてUDPをブロックしますか?簡単な説明。 –

+0

私はファイアウォールを有効にしていないので、そうではありません。さらに、bootpcクライアントは期待通りに動作します。実際には、このコードのrecvを除いてすべてが期待通りに機能します。私はちょうどなぜUDP recvが他の場所でも動作しているのですが、ここでは動作しません。 – stativ

答えて

1

OKは、これを理解するために数日かかったが、私は最終的にそれを修正しました。

問題は、私がrecvfromしようとしていたパケットが私のために運命づけられていないということでした。私は詳しく説明します。 bootpプロトコルでは、MACアドレスを送信し、サーバはブロードキャストまたはMACアドレスで接続されたIPに応答を送信します。問題は、他のコンピュータのMACアドレスを使用していたため、返信がそのコンピュータに宛てられたものであり、私にとってではありませんでした。

これはそうです。何も届かない場合は、あなたが目的地であることを確認してください。

関連する問題