Raw Sockets: Receptor imprimiendo valores basura
Frecuentes
Visto 2,164 veces
0
Estoy tratando de enviar una matriz de caracteres usando un transmisor y un programa receptor usando sockets sin formato. Puedo obtener la cantidad correcta de bytes enviados en el lado del receptor, pero los valores impresos son basura. ¿Podría alguien ayudarme aquí?
Transmisor:
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;
}
Receptor
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 Respuestas
2
Cambiar
write(sockaddress, &send_packet, packet_len)
a
write(sockaddress, send_packet, packet_len)
send_packet
ya es la dirección del búfer a enviar, si toma la dirección de esta dirección (más precisamente, la dirección de la variable que contiene la dirección), leerá la memoria incorrecta para el búfer
Similarmente para recvfrom
:
recvfrom(sock_fd, buf, sizeof(buf), 0, &addr, &fromlen)
contestado el 22 de mayo de 12 a las 16:05
2
Tienes varios problemas:
Esta línea
if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len)
Debería decir solo
send_packet
en lugar de&send_packet
.send_packet
es un puntero que apunta al paquete de datos deseado, por lo que no es necesario tomar su dirección; no desea escribir la dirección literal de ese puntero en el paquete, eso simplemente no funcionará.Esto está mal:
char *send_packet="HELLO"; int len = sizeof(send_packet);
sizeof(send_packet)
siempre tendrá el tamaño de un puntero en su sistema, típicamente 4 u 8 bytes. Realmente quieres declararsend_packet
como un tipo de matriz (por ejemplochar send_packet[] = ...
), o usarstrlen
para calcular su longitud en tiempo de ejecución (por ejemplo,int len = strlen(send_packet) + 1;
). En su caso, está enviando muy pocos datos (4 bytes) o demasiados datos (8 bytes), los cuales son problemáticos.Tus
printf
El código en el cliente asume que los datos que recibe están terminados en nulo, lo cual no es necesariamente. Debe anular manualmente los datos antes de imprimirlos (o usar cualquier otra función de cadena, para el caso), o decirleprintf
el límite de la cantidad de datos para imprimir. Sugeriría terminarlo en nulo así: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;
Su código tiene mala
const
exactitud.SendPacket
debería tomar unconst char*
en lugar dechar*
parámetro, ysend_packet
debe ser declarado comochar[]
o comoconst char*
. La conversión de cadenas literales achar*
está en desuso y debe evitarse en todo el código C nuevo.
contestado el 22 de mayo de 12 a las 16:05
Gracias por señalar todo el problema. Lo corregiré en mi código. Gracias de nuevo. - hektor
0
El uso de printf para imprimir el búfer imprimirá una cadena hasta que se alcance el final del carácter de cadena. Si ve la cadena original seguida de caracteres basura, esta puede ser la razón.
Probablemente debería introducir un 0 después del último byte devuelto por recvfrom, o imprimirá cualquier valor que haya en la memoria que recvfrom no sobrescribió. Incluso podría intentar acceder a la memoria fuera del búfer.
Intente agregar algo como:
int x= recvfrom(sock_fd,&buf,sizeof(buf) - 1,0,&addr,&fromlen);
buf[x - 1] = 0;
Nota: eso cambia el tamaño máximo de lo que se lee, es solo un ejemplo de cómo hacerlo.
contestado el 22 de mayo de 12 a las 16:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c sockets raw-sockets or haz tu propia pregunta.
Eso es correcto para el
write
llamar, ya quesend_packet
es un puntero, pero no hace ninguna diferencia para la llamada arecvfrom
, Desdebuf
es una matriz. Los tipos de matriz tienen la propiedad de que su dirección es numéricamente equivalente a la dirección de su primer elemento, por lo que para una matrizx
, siempre es cierto que(void*)&x == (void*)&x[0]
. - adam rosenfield