[英]Raw Sockets : Receiver printing garbage values
我正在尝试使用原始套接字在发送器和接收器程序之间发送字符数组。 我能够获得在接收方发送的正确字节数,但是打印出的值是垃圾。 有人可以帮我吗?
发射机:
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)
您有几个问题:
这条线
if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len)
应该说的只是send_packet
而不是&send_packet
。 send_packet
是一个指向所需数据包数据的指针,因此无需获取其地址-您不想将该指针的字面地址写到数据包中,这简直是行不通的。
这是错误的:
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个字节),这两者都是有问题的。
客户端中的printf
代码假定接收到的数据以null终止,但不一定如此。 您应该在打印之前手动对数据进行null终止(或使用其他任何字符串函数),或者告诉printf
要打印多少数据的限制。 我建议像这样以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;
您的代码的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;
注意:这会更改读取的最大大小,这只是如何执行此操作的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.