0

我正在尝试使用发送器和使用原始套接字的接收器程序跨字符数组发送。我能够获得在接收端发送的正确字节数,但打印出来的值是垃圾。有人可以帮我吗?

发射机:

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在客户端中的代码假定它接收到的数据是空终止的,但不一定如此。您应该在打印数据之前手动终止数据(或使用任何其他字符串函数,就此而言),或者告诉printf要打印多少数据的限制。我建议像这样终止它:

    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应采用 aconst char*而不是char*参数,并且send_packet应声明为char[]或 as const char*。从字符串文字到的转换char*已被弃用,应在所有新的 C 代码中避免。

于 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 回答