Невозможно использовать send() для отправки .exe в программировании на c

StackOverflow https://stackoverflow.com/questions/2082682

  •  21-09-2019
  •  | 
  •  

Вопрос

Я создаю серверно-клиентскую программу на c и у меня возникли некоторые проблемы с отправкой целого файла с помощью функций send () и recv().Мне нужно отправить весь файл с ними, но все, что эти функции могут сделать, это отправить строку.Основная проблема связана с отправкой exe-файла или других двоичных данных formet.Должен ли я использовать htons или htonl func?Я не знаю, как использовать их вместе с этими, поскольку я всего лишь нуб.

Я застрял с этим и люблю вашу помощь.Спасибо!!

Вот функция 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);

Функция отправки на стороне клиента :::

аннулирует отправку_команды() { int байтовое отправление;ФАЙЛ *file_out;//file_out = открыть(путь к файлу, "rb");char str_all[100000];//флаг [30]="конец";

///////////////////////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;
}
Это было полезно?

Решение

Вам нужно будет реализовать эту функциональность самостоятельно или использовать библиотеку, которая это делает. send(2) просто отправляет необработанный байтовый буфер.Если вы хотите отправить файл, вам нужно будет использовать какой-то протокол это понимают и клиент, и сервер.

Самым простым из возможных протоколов может заключаться в том, чтобы клиент отправлял имя файла, длину файла, а затем необработанные данные файла.Например (проверка ошибок опущена для наглядности):

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

Кроме того, будьте осторожны с частичными отправками / получениями.Убедитесь, что вы проверяете возвращаемые значения из send и recv, поскольку они могут (и часто делают) отправлять или получать только подмножество данных, которые вы намереваетесь отправить или получить.Когда это происходит, вам приходится восстанавливаться путем повторной отправки или получения в цикле до тех пор, пока вы не обработаете все данные, которые вы намеревались, или не возникнет ошибка.

В качестве альтернативы использованию вашего собственного протокола вы можете использовать существующий протокол с библиотекой, такой как libftp ( либфтп ) или libcurl.

Другие советы

send() отправляет не строку, а массив байтов.Вы создаете свой буфер, заполняете его, отправляете буфер и передаете количество байтов в нем в send(), а оттуда.

В зависимости от операционной системы, в которой вы работаете, может быть sendfile команда;но это не гарантирует переносимости в разных операционных системах.Самый портативный способ - это просто read() файл в виде фрагментов помещается в буфер, а затем write() это вне (или send() это исключено, если вы используете сокет, хотя write() тоже должно работать просто отлично).

Видишь мой ответ на этот предыдущий вопрос спрашиваю, по сути, то же самое.

Что вам нужно сделать, так это отправлять свои данные несколькими порциями, по одной за раз.Итак, по сути, вы считываете свой файл по N байт за раз в буфер и отправляете() эти N байт.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top