简体   繁体   English

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

[英]Raw Sockets : Receiver printing garbage values

I am trying to send across a character array using a transmitter and a receiver program using raw sockets. 我正在尝试使用原始套接字在发送器和接收器程序之间发送字符数组。 I am able to get the correct number of bytes sent at the receiver side, but the values printed out are garbage. 我能够获得在接收方发送的正确字节数,但是打印出的值是垃圾。 Could someone help me out here? 有人可以帮我吗?

Transmitter: 发射机:

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

Receiver : 接收方:

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

Change 更改

write(sockaddress, &send_packet, packet_len)

to

write(sockaddress, send_packet, packet_len)

send_packet is already the address of the buffer to be sent, if you take the address of this address (more precisely the address of the variable holding the address), you will read the wrong memory for the buffer send_packet已经是要发送的缓冲区的地址,如果采用该地址的地址(更确切地说是保存该地址的变量的地址),则会读取该缓冲区的错误内存

Similarly for recvfrom : 对于recvfrom同样:

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

You have several problems: 您有几个问题:

  1. This line 这条线

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

    Should say just send_packet instead of &send_packet . 应该说的只是send_packet而不是&send_packet send_packet is a pointer that points to the desired packet data, so there's no need to take its address -- you don't want to write out the literal address of that pointer into the packet, that just simply won't work. send_packet是一个指向所需数据包数据的指针,因此无需获取其地址-您不想将该指针的字面地址写到数据包中,这简直是行不通的。

  2. This is wrong: 这是错误的:

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

    sizeof(send_packet) will always be the size of a pointer on your system, typically either 4 or 8 bytes. sizeof(send_packet)将始终是系统上指针的大小,通常为4或8个字节。 You really want to either declare send_packet as an array type (eg char send_packet[] = ... ), or use strlen to compute its length at runtime (eg int len = strlen(send_packet) + 1; ). 您确实想将send_packet声明为数组类型(例如, char send_packet[] = ... ),或者在运行时使用strlen计算其长度(例如, int len = strlen(send_packet) + 1; )。 In your case, you're either sending too little data (4 bytes) or too much data (8 bytes), both of which are problematic. 在您的情况下,您发送的数据太少(4个字节)或数据太多(8个字节),这两者都是有问题的。

  3. Your printf code in the client assumes that the data it receives is null-terminated, which it is not necessarily. 客户端中的printf代码假定接收到的数据以null终止,但不一定如此。 You should either manually null-terminate the data before printing it (or using any other string functions, for that matter), or tell printf the limit of how much data to print. 您应该在打印之前手动对数据进行null终止(或使用其他任何字符串函数),或者告诉printf要打印多少数据的限制。 I'd suggest null-terminating it like so: 我建议像这样以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. Your code has poor const correctness. 您的代码的const正确性很差。 SendPacket should take a const char* instead of char* parameter, and send_packet should either be declared as char[] or as const char* . SendPacket应该采用const char*而不是char*参数,并且send_packet应该声明为char[]const char* The conversion from string literals to char* is deprecated and should be avoided in all new C code. 从字符串文字到char*的转换已被弃用,在所有新的C代码中都应避免。

Using printf to print the buffer will print a string until the en of string character is reached. 使用printf来打印缓冲区将打印一个字符串,直到达到字符串字符的en。 If you see the original string followed by garbage characters, this may be the reason. 如果看到原始字符串后跟垃圾字符,则可能是原因。

You should probably introduce a 0 after the last byte returned by recvfrom, or you will print whatever value was in the memory that recvfrom did not overwrite. 您可能应该在recvfrom返回的最后一个字节之后加上0,否则您将打印出recvfrom没有覆盖的内存中的任何值。 It could even try to access memory outside the buffer. 它甚至可以尝试访问缓冲区外部的内存。

Try adding something like: 尝试添加如下内容:

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

Note: that changes the maximum size of what is read, it is just an example of how to do it. 注意:这会更改读取的最大大小,这只是如何执行此操作的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM