Pregunta

Estoy construyendo un programa de servidor-cliente con C y tener un poco de todo un archivo problen wtih Sendiña con la función recv send () () y. Necesito enviar el archivo completo con ellos, pero todas estas funciones se puede hacer es enviar una cadena. El principal problema es con el envío del exe u otros datos binarios Formet. ¿Debo usar htons o htonl func? No sé cómo utilizar los largo de estos como yo soy más que un novato.

Estoy atascado con esto y quiero su ayuda. Gracias !!

Esta es la función de servidor de lado recv ::

if (socket_type != SOCK_DGRAM)
    {

            fi = fopen (final,"wb");
            retval = recv(msgsock, recv_buf, strlen(recv_buf), 0);
            /*recv_buf[retval] = '\0';
            fprintf (fi,"%s",recv_buf);*/

            int i;
            i=atoi(recv_buf);
            char *q;
            q=(char *)malloc(i*sizeof(char));
            retval = recv(msgsock, q, strlen(q), 0);
            //printf ("%s",q);
            fwrite(q,i,1,fi);
            fclose(fi);

    }
    else
    {
        retval = recvfrom(msgsock,recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from, &fromlen);
        printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
        printf ("SOCK_DGRAM");
    }

    if (retval == SOCKET_ERROR)
    {
        fprintf(stderr,"Server: recv() failed: error %d\n", WSAGetLastError());
        closesocket(msgsock);
        //continue;
    }
    else
        printf("Server: recv() is OK.\n");

    if (retval == 0)
    {
        printf("Server: Client closed connection.\n");
        closesocket(msgsock);
            //continue;
    }
    printf("Server: Received %d bytes, data from client\n", retval);

La función de envío del cliente :::

void send_command () {     int bytesent;     ARCHIVO * file_out;     // file_out = fopen (FILE_PATH, "rb");     Char str_all [100,000]; // bandera [30] = "fin";

///////////////////////getsize//////////////
char fsize[5];
int filesize;
file_out = fopen(file_path, "rb");
fseek(file_out, 0, SEEK_END);
filesize = ftell(file_out);
rewind (file_out);
itoa (filesize,fsize,10);
/////////////////////////////////////////////
send (ConnectSocket, fsize, strlen (fsize), 0);

char *r = (char *)malloc (filesize * sizeof(char));

fread(r,filesize,1,file_out);
bytesent = send( ConnectSocket, r, strlen(r), 0 );
printf("\nClient: Bytes sent: %ld\n", bytesent);
fclose (file_out);

/*while (fscanf(file_out,"%s",&str_all) != EOF)
{
    bytesent = send( ConnectSocket, str_all, strlen(str_all), 0 );
    printf("\nClient: Bytes sent: %ld\n", bytesent);
    //Sleep(500);
}*/

/*printf("%s",flag);
send( ConnectSocket, flag, strlen(flag), 0 );*/
WSACleanup();
//return 0;
}
¿Fue útil?

Solución

Usted necesitará para implementar la funcionalidad que usted mismo, o usar una biblioteca que lo hace. send(2) simplemente envía una memoria intermedia de bytes en bruto. Si desea enviar un archivo, tendrá que utilizar algún tipo de protocolo que tanto el cliente y el servidor de entender.

El protocolo simple posible podría ser que el cliente envíe el nombre del archivo, la longitud del archivo y el archivo de datos en bruto. Por ejemplo (comprobación de errores omite para mayor claridad):

// Server:
const char *filename = ...;
uint32_t filenameLen = strlen(filename);
uint32_t filenameLenNet = htonl(filenameLen);
send(fd, &filenameLenNet, sizeof(filenameLenNet), 0);
send(fd, filename, filenameLen, 0);

// You should probably use a 64-bit file length; also, for large files, you
// don't want to read the entire file into memory, you should just stream it
// from disk to network in reasonably-sized chunks.
const void *fileData = ...;
uint32_t fileLen = ...;
uint32_t fileLenNet = htonl(fileLen);
send(fd, &fileLenNet, sizeof(fileLenNet), 0);
send(fd, fileData, fileLen, 0);

// Client:
char *filename;
uint32_t filenameLen;
recv(fd, &filenameLen, sizeof(filenameLen), 0);
filenameLen = ntohl(filenameLen);
filename = malloc(filenameLen + 1);
recv(fd, filename, filenameLen, 0);
filename[filenameLen] = 0;
uint32_t fileLen;
recv(fd, &fileLen, sizeof(fileLen), 0);
fileLen = ntohl(fileLen);
void *fileData = malloc(fileLen);
recv(fd, fileData, fileLen, 0);
// Write file Data to the output file.  Again, for large files, it would be
// better to stream it in in chunks instead of reading it all in at once.

También, tener cuidado parcial envía / recibe. Asegúrese de verificar los valores de retorno de send y recv, ya que pueden (y lo hacen) a menudo sólo se envía o recibe un subconjunto de los datos que la intención de enviar o recibir. Cuando esto sucede, usted tiene que recuperar volviendo a enviar o rereceiving en un bucle hasta que haya procesado todos los datos que pretende o se produce un error.

Como alternativa a la utilización de su propio protocolo, se puede utilizar un protocolo existente con una biblioteca como libftp o libcurl .

Otros consejos

send () no envía una cadena, se envía una matriz de bytes. Usted crea su memoria intermedia, llenarlo, envía el búfer y pasa el # de Bytes para enviar (), y desde allí.

En función del sistema operativo que se encuentra, puede haber un comando sendfile ; pero no se garantiza que funcione de forma portátil a través de diferentes sistemas operativos. La forma más portátil es simplemente read() el archivo en trozos en en un búfer, y entonces write() a cabo (o send() a cabo, si está usando un enchufe, aunque write() debería funcionar bien también).

mi respuesta a esta pregunta anterior pidiendo esencialmente la misma cosa.

Lo que tienes que hacer es enviar sus datos en varios trozos, de un pedazo a la vez. Así que, esencialmente, se lee su archivo de N bytes a la vez en un búfer y send () aquellos N bytes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top