Non è possibile usare send () per inviare .exe nella programmazione c
Domanda
Sto costruendo un programma server-client con C e avere qualche un intero file problen addebbitato sendina con send () e la funzione recv (). Ho bisogno di inviare l'intero file con questi, ma tutte queste funzioni possono fare è inviare una stringa. Il problema principale è con l'invio del exe o altri dati FORMET binari. Dovrei usare htons o htonl func? Non so come utilizzare quelli lungo questi come io sono soltanto un noob.
Sono bloccato con questo e amo il tuo aiuto. Grazie !!
Questa è la funzione di server side 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 funzione di invio lato client :::
send_command void () { int bytesent; FILE * file_out; // file_out = fopen (file_path, "rb"); char str_all [100000]; // bandiera [30] = "fine";
///////////////////////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;
}
Soluzione
È necessario implementare tale funzionalità se stessi, o utilizzare una libreria che fa. send(2)
solo manda un buffer di byte grezzo. Se si desidera inviare un file, è necessario utilizzare una sorta di protocollo che sia il client e il server capiscono.
Il protocollo più semplice possibile potrebbe essere quella di avere il client invia il nome del file, la lunghezza del file, e quindi i dati del file grezzi. Ad esempio (controllo degli errori omesso per chiarezza):
// 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.
Inoltre, essere attenti a parziale invia / riceve. Assicurati di controllare i valori restituiti dalla send
e recv
, dal momento che possono (e fare) spesso solo di inviare o ricevere un sottoinsieme dei dati che l'intenzione di inviare o ricevere. Quando ciò accade, è necessario recuperare da inviare nuovamente o rereceiving in un ciclo fino a quando hai elaborato tutti i dati previsto o si verifica un errore.
In alternativa utilizzando il proprio protocollo, è possibile utilizzare un protocollo esistente con una libreria come libftp o libcurl .
Altri suggerimenti
send () non invia una stringa, invia una matrice di byte. Si crea il buffer, riempirlo, inviare il buffer e passa il # di byte per inviare (), e da lì.
A seconda del sistema operativo si è in, ci può essere un comando sendfile
; ma non è garantito il funzionamento portabile su diversi sistemi operativi. Il modo più portatile è ad appena read()
il file in in blocchi in un buffer, e poi write()
fuori (o send()
fuori, se si sta utilizzando una presa, anche se write()
dovrebbe funzionare bene anche).
la mia risposta a questa domanda precedente chiedendo essenzialmente la stessa cosa.
Quello che devi fare è quello di inviare i tuoi dati in blocchi diversi, un pezzo alla volta. Quindi, in sostanza, di leggere i vostri file di N byte alla volta in un buffer e inviare () tali byte N.