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

Я создаю сервер-клиентскую программу с c и у меня возникли проблемы с sendina целым файлом с функциями 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);

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

void send_command () { int bytesent; FILE * file_out; // file_out = fopen (file_path, "rb"); char str_all [100000]; // flag [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;
}

Ответы [ 4 ]

3 голосов
/ 18 января 2010

Вам нужно будет реализовать эту функцию самостоятельно или использовать библиотеку, которая делает это. 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 .

3 голосов
/ 18 января 2010

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

2 голосов
/ 18 января 2010

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

См. мой ответ на этот предыдущий вопрос задавая по существу то же самое.

1 голос
/ 18 января 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...