【问题标题】:Raw Sockets : Receiver printing garbage values原始套接字:接收器打印垃圾值
【发布时间】:2012-05-22 15:00:42
【问题描述】:

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

发射器:

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;
 }

【问题讨论】:

    标签: c sockets raw-sockets


    【解决方案1】:

    改变

    write(sockaddress, &send_packet, packet_len)
    

    write(sockaddress, send_packet, packet_len)
    

    send_packet已经是要发送的缓冲区的地址,如果你取这个地址的地址(更准确地说是保存地址的变量的地址),你会为缓冲区读取错误的内存

    同样适用于recvfrom

    recvfrom(sock_fd, buf, sizeof(buf), 0, &addr, &fromlen)
    

    【讨论】:

    • 这对于write 调用是正确的,因为send_packet 是一个指针,但是对于recvfrom 的调用没有区别,因为buf 是一个数组。数组类型具有其地址在数值上等价于其第一个元素的地址的属性,因此对于数组x(void*)&x == (void*)&x[0] 总是正确的。
    【解决方案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 应该采用const char* 而不是char* 参数,并且send_packet 应该声明为char[]const char*。从字符串文字到 char* 的转换已被弃用,应在所有新的 C 代码中避免。

    【讨论】:

    • 感谢您指出所有问题。将在我的代码中更正它。再次感谢。
    【解决方案3】:

    使用 printf 打印缓冲区将打印一个字符串,直到到达字符串字符的 en。如果您看到原始字符串后跟垃圾字符,则可能是这个原因。

    您可能应该在 recvfrom 返回的最后一个字节之后引入一个 0,否则您将打印内存中 recvfrom 没有覆盖的任何值。它甚至可以尝试访问缓冲区之外的内存。

    尝试添加类似的内容:

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

    注意:这会改变读取内容的最大大小,这只是一个示例。

    【讨论】:

      猜你喜欢
      • 2013-05-25
      • 1970-01-01
      • 1970-01-01
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多