2010-01-17 15 views
1

Je construis un programme client-serveur avec c et j'ai des problèmes avec sendina avec un fichier entier avec la fonction send() et recv(). Je dois envoyer le fichier entier avec ceux-ci mais toutes ces fonctions peuvent faire est d'envoyer une chaîne. Le problème principal est l'envoi de l'exe ou d'autres données de format binaire. Devrais-je utiliser htons ou htonl func? Je ne sais pas comment utiliser ceux-ci le long de ceux-ci comme je suis simplement un noob. Je suis coincé avec cela et j'adore votre aide. Merci!!Impossible d'utiliser send() pour envoyer .exe dans la programmation c

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 (chemin_fichier, "rb"); char str_all [100000]; // indicateur [30] = "fin"; Send() n'envoie pas de chaîne, il envoie un tableau d'octets.

///////////////////////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; 
} 
+0

Ceci crée un fichier avec le nom et la taille souhaités mais pas le contenu. C'est le gros problème! C'est aussi pour les fenêtres !! –

Répondre

3

Vous devrez vous-même implémenter cette fonctionnalité ou utiliser une bibliothèque qui le fait. send(2) envoie juste un tampon d'octet brut. Si vous voulez envoyer un fichier, vous devez utiliser un protocole que le client et le serveur comprennent.

Le protocole le plus simple possible peut être que le client envoie le nom de fichier, la longueur du fichier, puis les données du fichier brut. 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 ne le font) souvent envoyer ou recevoir un sous-ensemble des données que vous avez l'intention d'envoyer ou de recevoir. Lorsque cela se produit, vous devez récupérer en renvoyant ou en recevant à nouveau une boucle jusqu'à ce que vous ayez traité toutes les données voulues ou qu'une erreur se soit produite. Comme alternative à l'utilisation de votre propre protocole, vous pouvez utiliser un protocole existant avec une bibliothèque telle que libftp ou libcurl.

+0

Cette fonction est pour la variable 32 bits sur Linux, pouvez-vous me parler de la variable Windows? pLease Ce sera une aide précieuse car je ne peux pas l'implémenter dans Windows. –

3

send() n'envoie pas de chaîne. Vous créez votre tampon, le remplissez, envoyez le tampon et passez le # d'octets dedans à send(), et à partir de là.

2

Selon le système d'exploitation utilisé, il peut y avoir une commande sendfile; mais il n'est pas garanti de fonctionner de manière portative entre différents systèmes d'exploitation. Le moyen le plus portable est de simplement read() le fichier en morceaux dans un tampon, puis write() il (ou send() il, si vous utilisez une socket, si write() devrait fonctionner très bien aussi).

Voir my answer to this previous question demandant essentiellement la même chose.

1

Ce que vous avez à faire est d'envoyer vos données en plusieurs morceaux, un morceau à la fois. Donc, essentiellement vous lisez votre fichier N octets à la fois dans un tampon et envoyez() ces N octets.