原始套接字:接收方打印垃圾值

时间:2012-05-22 15:00:43

标签: c sockets raw-sockets

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

发射器:

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

3 个答案:

答案 0 :(得分:2)

更改

write(sockaddress, &send_packet, packet_len)

write(sockaddress, send_packet, packet_len)

send_packet已经是要发送的缓冲区的地址,如果你取这个地址的地址(更确切地说是保存地址的变量的地址),你将读取缓冲区的错误内存< / p>

同样适用于recvfrom

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

答案 1 :(得分: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代码中避免使用。

答案 2 :(得分:0)

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

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

尝试添加以下内容:

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

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