sockets - example - socket udp sendto
recvde volver a leer los datos en el socket (1)
En los casos de falla (es decir, si recvfrom o cuando select devuelve el tiempo de espera) también está devolviendo "buffer" que no se inicializa, por lo que los contenidos pueden ser datos anticipados pero el comportamiento no está definido. Por lo tanto, es mejor que lo inicialice en 0 (memset (& buffer, 0, sizeof (struct packet))) en el comienzo antes de llamar a recvfrom
En el ciclo while está buscando (receivedPacket.flags == NORMAL), si es NORMAL
entonces solo está imprimiendo el búfer y llamando a la función nuevamente.En la función "receivePacket" al seleccionar timeout o recvfrom failure (s) explicity, actualice los "receivedPacket.flags" a otros NORMAL para que se queden mientras el loop se romperá.
Estoy creando un programa simple de socket UDP de servidor / cliente y me he encontrado con un problema.
El problema es que la función recvfrom () continúa volviendo a leer los últimos datos que se enviaron.
Entonces, si envío dos paquetes del cliente al servidor, entonces recvfrom () leerá el primer paquete e imprimirá sus datos, luego leerá constantemente el segundo paquete una y otra vez.
Según entiendo, el paquete se debe quitar del socket una vez que se haya realizado una operación de lectura exitosa, pero eso no parece estar sucediendo.
Sé con certeza que el cliente no está reenviando los datos ya que hay una salida de la consola que se escribe cada vez que el cliente envía datos.
Aquí está la función para el remitente
int sendPacket(int socketFd, int type, char *typeString, char *data, int seq, int windowSize, struct sockaddr_in serverName) {
struct packet *sendPacketPtr, sendPacket;
fd_set writeFdSet;
sendPacketPtr = &sendPacket;
sendPacket.flags = type;
sendPacket.windowsize = windowSize;
sendPacket.seq = seq;
sendPacket.id = getpid();
if (type == NORMAL)
strcpy(sendPacket.data, data);
FD_ZERO(&writeFdSet);
FD_SET(socketFd, &writeFdSet);
if(select(FD_SETSIZE, NULL, &writeFdSet, NULL, NULL) > 0) {
if(sendto(socketFd, sendPacketPtr, sizeof(sendPacket), 0, (struct sockaddr *)&serverName, sizeof(serverName)) < 0) {
printf("%s packet was not sent/n", typeString);
perror("Send error");
} else {
printf("%s packet was sent/n", typeString);
}
}
return 0;
}
Que se llama con este bucle que se ejecuta dos veces para sus valores dados.
for (int i = seqBase; i <= seqMax && i < packetNum; i++) {
sendPacket(socketFd, NORMAL, "DATA", dataArray[i], i, 0, serverName);
}
Y la función de recepción
struct packet receivePacket (int socketFd, struct sockaddr_in *address, int timeout, int useTimeout) {
struct packet buffer;
fd_set readFdSet;
struct sockaddr_in dest_addr;
struct timeval selectTimeout;
selectTimeout.tv_usec = 0;
selectTimeout.tv_sec = timeout;
FD_ZERO(&readFdSet);
FD_SET(socketFd, &readFdSet);
socklen_t len = sizeof(dest_addr);
if(useTimeout == 0) {
if(select(FD_SETSIZE, &readFdSet, NULL, NULL, NULL) > 0) {
if(recvfrom(socketFd, &buffer, sizeof(buffer), 0, (struct sockaddr *)&dest_addr, &len) < 0) {
perror("Read error");
}else {
*address = dest_addr;
}
}
}else {
if(select(FD_SETSIZE, &readFdSet, NULL, NULL, &selectTimeout) > 0) {
if(recvfrom(socketFd, &buffer, sizeof(buffer), 0, (struct sockaddr *)&dest_addr, &len) < 0) {
perror("Read error");
}else {
*address = dest_addr;
}
}
}
return buffer;
}
Que se llama con este bucle desde el servidor
receivedPacket = receivePacket(socketFd, &destAddress, 0, 0);
while (receivedPacket.flags == NORMAL) {
printf("Data received: /"%s/", sequence: %d/n", receivedPacket.data, receivedPacket.seq);
receivedPacket = receivePacket(socketFd, &destAddress, TIMEOUT, 1);
}
Y el resultado que se ejecuta para siempre (ya que sigue volviendo a leer el último paquete) es:
Data received: "Packet 0", sequence: 0
Data received: "Packet 1", sequence: 1
Data received: "Packet 1", sequence: 1
Data received: "Packet 1", sequence: 1
Data received: "Packet 1", sequence: 1
........