Socket C

Garayo

Hola buenas, estoy trabajando en el envío de imágenes entre una FPGA y un PC. Me han recomendado el uso del protocolo LwIP pero al final me he decantado por hacerlo en UNIX normal. Hace tiempo hice un socket con para pasar datos (cabecera + payload) y no tuve ningún problema pero las imágenes se me están resistiendo. Compila sin errores pero no hace lo que tiene que hacer, recibe o tamaño de datos negativos o 0 y a partir de ahí no hace más (lógicamente).

Este es el código que uso en el cliente (Que tiene que recibir que las imágenes):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdint.h>


struct image { 
	int size;
	char p_array[500000];
};

void main () {

struct image img;

int sock, addrlen;				//Definir variables Socket

sock = socket(AF_INET,SOCK_STREAM,0);			// Definimos sock como socket

if(sock < 0) {
perror("Error creating the socket");			// Comprobar que la funcion socket no es erronea
}
							
struct sockaddr_in their_addr;					//Variable their_addr del tipo struct sockaddr

their_addr.sin_family = AF_INET; 													//Definimos valores a la struct sockaddr_in
their_addr.sin_port = htons (1990);											// Lo asigna al puerto 1234
their_addr.sin_addr.s_addr = inet_addr ("192.168.0.6");  		//Para que use cualquier IP valida para la máquina

addrlen = sizeof (struct sockaddr);

int conectar;

conectar = connect (sock, (struct sockaddr *)&their_addr, addrlen);

if (conectar<0) {
	printf("Error al conectar\n");
}

//Logica de aplicacion

//Leer tamaño de imagen

printf("Reading Picture Size\n");

recv(sock, &img, sizeof(img),0);

printf("Recibido tamano: %d\n", img.size);

//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
read(sock, img.p_array, img.size);

printf("Leido tamano\n");

//Convert it Back into Picture
printf("Converting Byte Array to Picture\n");
FILE *image;
image = fopen("c1.jpg", "w");
fwrite(img.p_array, 1, sizeof(img.p_array), image);
fclose(image);

}

Y este sería el servidor (que es el que tiene que enviar las imágenes):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h> 


#define ALTO 480
#define ANCHO 640
#define PIXEL 4
#define OFFSET 0x0e000000

struct image{
	int size;
	char send_buffer[500000];
};


int main () {

int sock,new_sock, addrlen,backlog,cerrar, pkt_rx;
int leidos = 0;
int enviados = 0;
int DimImagen= ALTO*ANCHO*PIXEL; //tamaño de la imagen
char buffer[DimImagen];
struct image img;

backlog = 1;

sock = socket(PF_INET,SOCK_STREAM,0);			// Definimos sock como socket, PF_INET = dominio donde se realiza la conexion, SOCK_STREAM = tipo de socket q se va a crear.

if(sock < 0) {
perror("Error creating the socket");			// Comprobar que la funcion socket no es erronea
}


struct sockaddr_in my_addr;							//Variable my_addr de tipo stuct sockaddr
struct sockaddr_in their_addr;					//Variable their_addr del tipo struct sockaddr

my_addr.sin_family = PF_INET; 													//Definimos valores a la struct sockaddr_in
my_addr.sin_port = htons (1990);											// Lo asigna al puerto 1234
my_addr.sin_addr.s_addr = htonl (INADDR_ANY);  //Para que use cualquier IP valida para la máquina


addrlen = sizeof(struct sockaddr);			

if (bind(sock, (struct sockaddr *)&my_addr,addrlen) <0) {	//Función BIN sirve para asociar estos parámetros. 

		perror("Error bind"); 				//Comprobamos si la funcion bind es correcta
}


if (listen(sock, backlog) == -1)
{ 

perror("Error listen");						//Comprobamos si la funcion listen es correcta
	
}	

for(;;){
	
new_sock = accept (sock, (struct sockaddr *)&their_addr, &addrlen); 

printf("Estoy conectado\n");

//Get Picture Size
printf("Getting Picture Size\n");
FILE *picture;
picture = fopen("/home/diego/Desktop/gato.jpg", "r");
//int size;
fseek(picture, 0, SEEK_END);
img.size = ftell(picture);

printf("tamano imagen: %i\n",img.size);
fseek(picture, 0, SEEK_SET);

//conv = htonl(size);
//Send Picture Size
printf("Sending Picture Size: %d conv: \n", img.size);
send(sock, &img, sizeof(img), 0);

printf("archivo enviado\n");

//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
//char send_buffer[size];
while(!feof(picture)) {
	fread(img.send_buffer, 1, sizeof(img.send_buffer), picture);
	send(sock, &img, sizeof(img),0);
	bzero(img.send_buffer, sizeof(img.send_buffer));
}

}

printf("Envio completo\n");

// recv(new_sock, &cerrar, sizeof(cerrar), 0);

close(new_sock); 
close(sock);

}

La verdad es que me gustaría coger las imágenes dinámicamente de memoria (pues vienen grabadas de una cámara y almacenadas) pero con conseguir que funcione de este modo podría ir tirando. No soy un programador profesional (como podeis comprobar XD) pero si tengo muchas ganas de mejorar y de ir aprendiendo en este campo. Acepto toda crítica y busco una solución auqí porque por más que lo miro no acabo de alcanzar a ver el fallos .Muchas gracias de antemano por vuestra atención!

MaSoBa

#1 Introduce el código entre las etiquetas

[code][ /code]
1
NoRelaX

No te puedo ayudar pero pon el código con los label

, por favor.
1
r2d2rigo

#1

send(sock, &img, sizeof(img), 0);

Estas enviando la estructura image, animal... normal que te salgan numeros raros, con eso envia el puntero. Envia img.size primero anda.

1 2 respuestas
Garayo

#4 Mañana pruebo y te comento. Porque ya probé enviando sin estructura y no salía, pero igualmente creo que tienes razón en que no es correcto lo que hago ahora. Mañana pruebo y te comento, muchísimas gracias :D

Garayo

#4 Al final hice como decías y tampoco funciona.... Dice 0Bytes recibidos. No se que puede estar fallando la verdad. Alguna idea?

1 respuesta
r2d2rigo

#6 has cambiado el recv para que tambien lea un int?

1 respuesta
Garayo

#7 Si si, lo cambié pero no hay manera. 0 bytes. Estoy trabajando ahora sobre este código que envía bien y el otro recibe bien pero no muestra la imagen para nada:

Servidor:

#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

int fileSEND(int PORT, char *lfile, char *rfile)
{
    int socketDESC;
    struct sockaddr_in serverADDRESS;
    FILE *file_to_send;
    int ch;
    char toSEND[1];
    char remoteFILE[4096];
    int percent;
    
socketDESC = socket(AF_INET, SOCK_STREAM, 0); if(socketDESC<0) { printf("Cannot create socket\n"); return 1; } serverADDRESS.sin_family = AF_INET; serverADDRESS.sin_addr.s_addr = inet_addr ("192.168.1.78"); serverADDRESS.sin_port = htons(PORT); if(connect(socketDESC,(struct sockaddr *)&serverADDRESS,sizeof(serverADDRESS))<0) { printf("Cannot connect\n"); return 1; } file_to_send = fopen(lfile, "r"); if(!file_to_send) { printf("Error opening file\n"); close(socketDESC); return 0; } else { long fileSIZE; fseek(file_to_send,0,SEEK_END); fileSIZE=ftell(file_to_send); rewind(file_to_send); printf("El tamano de la imagen es: %ld\n",fileSIZE); sprintf(remoteFILE,"FBEGIN:%s:%ld\r\n",rfile,fileSIZE); send(socketDESC,remoteFILE,sizeof(remoteFILE),0); percent = fileSIZE/100; while((ch=getc(file_to_send))!=EOF) { toSEND[0]=ch; send(socketDESC,toSEND,1,0); } } fclose(file_to_send); close(socketDESC); return 0; } int main() { fileSEND(1990, "gato.jpeg", "enviada.jpeg"); return 0; }

Cliente (creo que es donde está el fallo):

#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

#define PORT 1990

int parseARGS(char **args, char *line)
{
    int tmp = 0;
    args[tmp] = strtok(line, ":" );
    while ((args[++tmp] = strtok(NULL, ":" )) != NULL);
    return tmp -1;
}

int main()
{
    char *header[4096];
    int listenSOCKET, connectSOCKET;
    socklen_t clientADDRESSLENGTH;
    struct sockaddr_in clientADDRESS, serverADDRESS;
    char recvBUFF[4096];
    char *filename, *filesize;
    FILE *recvFILE;
    int received = 0;
    char tempstr[4096];
    
int percent; listenSOCKET = socket(AF_INET, SOCK_STREAM, 0); if (listenSOCKET <0) { printf("Cannot create socket\n"); close(listenSOCKET); return 1; } serverADDRESS.sin_family = AF_INET; serverADDRESS.sin_addr.s_addr = htonl(INADDR_ANY); serverADDRESS.sin_port = htons(PORT); if (bind(listenSOCKET, (struct sockaddr *)&serverADDRESS, sizeof(serverADDRESS))<0) { printf("Cannot bind socket\n"); close(listenSOCKET); return 1; } listen(listenSOCKET, 5); clientADDRESSLENGTH = sizeof(clientADDRESS); connectSOCKET = accept(listenSOCKET,(struct sockaddr *)&clientADDRESS, &clientADDRESSLENGTH); if (connectSOCKET<0) { printf("Cannot accpet connection\n"); close(listenSOCKET); return 1; } while(1) { printf("Conectado!!"); if(recv(connectSOCKET, recvBUFF, sizeof(recvBUFF),0)) { if(!strncmp(recvBUFF,"FBEGIN",6)) { recvBUFF[strlen(recvBUFF)-2] = 0; parseARGS(header, recvBUFF); filename = header[1]; filesize = header[2]; } recvBUFF[0] = 0; recvFILE = fopen(filename, "w"); printf("Dim imagen: %s\n", filesize); percent = atoi(filesize)/100; printf("Current percent value: %d\n",percent); while(1) { if(recv(connectSOCKET,recvBUFF,1,0) != 0) { fwrite(recvBUFF,sizeof(recvBUFF[0]),1, recvFILE); if(received < 50) printf("Recibido: %c\n", recvBUFF[0]); received++; recvBUFF[0] = 0; } else { close(listenSOCKET); return 0; } } close(listenSOCKET); } else { printf("Client dropped connection\n"); } return 0; } }
1 respuesta
r2d2rigo

#8 mas de lo mismo. Estas haciendo sizeof a un char[] y deberia ser strlen.

2 respuestas
Garayo

#9 Sugieres que defina el char toSEND como un strlen? No tengo muy claro el cambio que me quieres decir (si sobre el papel, no sobre C).

1 respuesta
gonya707

#10 si haces sizeof a un puntero como estas haciendo, te va a devolver los bits que mide la dirección de memoria y eso no es lo que quieres, usa strlen en vez de sizeof

1 respuesta
Garayo

#9 #11 Muchísimas gracias a los dos!! Ya he conseguido que funcione, era exactamente ese el cambio que tenía que hacer en el cliente (el que envía imágenes). Me ha parecido bastante interesante este tema.

Una pregunta (si no es mucho decir jeje), si quisiera coger imágenes de memoria e ir transmitiéndolas constante mente(modo "vídeo") tendría que usar el mmap con la dirección del buffer y a partir de ahí hacer un for infinito ?

Usuarios habituales

  • Garayo
  • gonya707
  • r2d2rigo
  • NoRelaX
  • MaSoBa