0

送信機を使用して文字配列を送信し、rawソケットを使用して受信機プログラムを送信しようとしています。受信側で送信された正しいバイト数を取得できますが、出力される値はごみです。誰かがここで私を助けてくれますか?

送信機:

int create_raw_socket(char *dev) 
{   
struct sockaddr_ll sll;
struct ifreq ifr;
int fd, ifi, rb;

bzero(&sll, sizeof(sll)); 
    bzero(&ifr, sizeof(ifr));

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

assert(fd != -1);

strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ);
ifi = ioctl(fd, SIOCGIFINDEX, &ifr);
assert(ifi != -1);
sll.sll_protocol = htons(ETH_P_ALL);
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
rb = bind(fd, (struct sockaddr *)&sll,sizeof(sll));
assert(rb != -1);

return fd;  
 }


int SendPacket(char *dev ,unsigned char *send_packet, int packet_len) 
{
   int num_sent= 0;
   int sockaddress = create_raw_socket(dev);

   if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len)
     { 

         close(sockaddress);
          return 0;
     } 
   else
     { 
        close(sockaddress);
         return 1; 
     }

  }


int main(int argc, char**argv)
{
   int x,fd,s; 

    char *send_packet="HELLO";

   int len = sizeof(send_packet);

   while(1)
   {

   if(!SendPacket((argv[1]), send_packet, len))
     perror("Error sending packet");
   else
     printf("Packet sent successfully with payload : %s\n" ,send_packet);
   }
    return 0; 
 }

受信機:

int main(int argc, char **argv)
{
 struct sockaddr addr;
 int sock_fd, fromlen,s;
 char buf[PACKET_LENGTH];
 char *dev = argv[1];


 while(1)
 {

   fromlen=sizeof(addr);
   sock_fd = create_raw_socket(dev);   /* Creating the raw socket */
   int x= recvfrom(sock_fd,&buf,sizeof(buf),0,&addr,&fromlen);
   printf("\n Number of bytes of data received is %d \n",x);

   printf("\nPayload  Received from client... is %s \n", buf);

   close(sock_fd);

 }
 return 0;
 }
4

3 に答える 3

2

変化する

write(sockaddress, &send_packet, packet_len)

write(sockaddress, send_packet, packet_len)

send_packetはすでに送信されるバッファーのアドレスです。このアドレスのアドレス (より正確には、アドレスを保持する変数のアドレス) を取得すると、バッファーに対して間違ったメモリを読み取ることになります。

同様にrecvfrom:

recvfrom(sock_fd, buf, sizeof(buf), 0, &addr, &fromlen)
于 2012-05-22T15:11:59.987 に答える
2

いくつかの問題があります。

  1. この行

    if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len)
    

    send_packetの代わりにちょうど言うべきです&send_packetsend_packetは、目的のパケット データを指すポインターであるため、そのアドレスを取得する必要はありません。そのポインターのリテラル アドレスをパケットに書き出す必要はありません。これは単に機能しません。

  2. これは間違っています:

    char *send_packet="HELLO";
    int len = sizeof(send_packet);
    

    sizeof(send_packet)は常にシステム上のポインターのサイズであり、通常は 4 または 8 バイトです。send_packet実際には、配列型として宣言するか(例: char send_packet[] = ...)、strlen実行時にその長さを計算するために使用する必要があります (例: int len = strlen(send_packet) + 1;)。あなたの場合、送信するデータが少なすぎる (4 バイト) か、多すぎる (8 バイト) かのどちらかであり、どちらも問題があります。

  3. printfクライアントのコードは、受信したデータが null で終了していると想定していますが、必ずしもそうとは限りません。データを印刷する前に (または他の文字列関数を使用して) 手動でデータを null で終了するか、印刷するprintfデータ量の制限を指定する必要があります。次のように null で終了することをお勧めします。

    char buf[PACKET_LENGTH + 1];  // +1 for null terminator
    int x = recvfrom(sock_fd,buf,PACKET_LENGTH,0,&addr,&fromlen);
    if(x >= 0)
        buf[x] = 0;
    
  4. あなたのコードはconst正しくありません。 パラメータの代わりに をSendPacket取り、 asまたは as として宣言する必要があります。文字列リテラルから への変換は推奨されておらず、すべての新しい C コードでは避ける必要があります。const char*char*send_packetchar[]const char*char*

于 2012-05-22T15:26:27.463 に答える
0

printf を使用してバッファーを出力すると、文字列文字の en に達するまで文字列が出力されます。元の文字列の後に文字化けが続く場合は、これが原因である可能性があります。

おそらく、recvfrom によって返された最後のバイトの後に 0 を導入する必要があります。または、recvfrom が上書きしなかったメモリ内の値を出力します。バッファ外のメモリにアクセスしようとすることさえあります。

次のようなものを追加してみてください:

int x= recvfrom(sock_fd,&buf,sizeof(buf) - 1,0,&addr,&fromlen);
buf[x - 1] = 0;

注:これは、読み取られるものの最大サイズを変更します。これは、それを行う方法の単なる例です。

于 2012-05-22T15:07:17.060 に答える