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

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

发射机:

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

更改

 write(sockaddress, &send_packet, packet_len) 

 write(sockaddress, send_packet, packet_len) 

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

同样对于recvfrom

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

你有几个问题:

  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代码中避免使用。

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

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

尝试添加以下内容:

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

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