Question

Je construis un programme client-serveur avec c et ayant une problen wtih sendina un fichier entier avec send () et la fonction recv (). Je dois envoyer le fichier entier avec ces derniers mais toutes ces fonctions peuvent faire est d'envoyer une chaîne. Le principal problème est d'envoyer l'exe ou d'autres données binaires Formet. Dois-je utiliser htons ou htonl func? Je ne sais pas comment utiliser les le long de ces que je suis simplement un noob.

Je suis coincé avec cela et aime votre aide. Merci !!

Voici la fonction côté serveur 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 fonction d'envoi côté client :::

send_command void () {     int bytesent;     FICHIER * file_out;     // file_out = fopen (file_path, "rb");     carbonisation str_all [100000]; // drapeau [30] = "end";

///////////////////////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;
}
Était-ce utile?

La solution

Vous aurez besoin de mettre en œuvre cette fonctionnalité vous-même, ou utiliser une bibliothèque qui le fait. send(2) envoie juste un tampon d'octets brut. Si vous voulez envoyer un fichier, vous aurez besoin d'utiliser une sorte de protocole que le client et le serveur comprennent.

Le plus simple protocole possible peut-être avoir le client envoie le nom du fichier, la longueur du fichier, puis les données de fichiers brutes. Par exemple (vérification d'erreur omis pour plus de clarté):

// 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.

Aussi, soyez prudent envoie / reçoit partielle. Assurez-vous de vérifier les valeurs de retour de send et recv, car ils peuvent (et faire) envoyer ou de recevoir souvent un sous-ensemble des données que vous l'intention d'envoyer ou de recevoir. Lorsque cela se produit, vous devez récupérer ou par réémission rereceiving dans une boucle jusqu'à ce que vous avez traité toutes les données voulues ou une erreur.

Comme alternative à l'utilisation de votre propre protocole, vous pouvez utiliser un protocole existant avec une bibliothèque, comme libftp ou libcurl .

Autres conseils

send () n'envoie pas une chaîne, il envoie un tableau d'octets. Vous créez votre tampon, remplissez-le, envoyez le tampon et passer le # d'octets à envoyer (), et à partir de là.

En fonction du système d'exploitation que vous êtes, il peut y avoir un la commande sendfile; mais il est pas garanti portably entre les différents systèmes d'exploitation. La façon la plus portable est juste read() le fichier en morceaux dans un tampon, et puis write() it out (ou send() dehors, si vous utilisez une prise, mais write() devrait fonctionner très bien aussi).

Voir ma réponse à cette question précédente demandant essentiellement la même chose.

Qu'est-ce que vous avez à faire est d'envoyer vos données en plusieurs morceaux, un morceau à la fois. Donc, pour l'essentiel de lire vos fichiers octets de N à la fois dans un tampon et d'envoyer () les N octets.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top