C: отправить файл в сокет - PullRequest
       41

C: отправить файл в сокет

5 голосов
/ 08 апреля 2011

Я пытаюсь отправить двоичный файл, используя сокет.

        FILE *file;
        char *file_data;
        file = fopen(filepath, "rb");

        //Allocate memory
        file_data=(char *)malloc(fileLen+1);

        //Read file contents into buffer
        fread(file_data, fileLen, 1, file);
        fclose(file);

        sent = send(client, file_data, strlen(header)+fileLen, 0);

Работает нормально, но некоторые файлы слишком велики, и я хочу прочитать часть в буфер, отправить ее, затем прочитать вторую часть, отправить ее и т. Д.

Я пытался получить детали, используя fread и fgets, но мне не удалось = (Как это сделать правильно?

UPD: проблема была в чтении входящего запроса от клиента. Я не читал это. Если я это сделаю, ничего плохого не случится

Ответы [ 4 ]

8 голосов
/ 08 апреля 2011

Что-то вроде:

#define CHUNK_SIZE 512

char file_data[CHUNK_SIZE];
//or
char *file_data = malloc(CHUNK_SIZE);

size_t nbytes = 0;
while ( (nbytes = fread(file_data, sizeof(char), CHUNK_SIZE)) > 0)
{
    sent = send(client, file_data, nbytes, 0);
}

Но вам также нужно отправить данные порциями, и вы не можете предполагать, что вы отправите все это за один вызов.

Чтобы send() выглядело так:

    int offset = 0;
    while ((sent = send(client, file_data + offset, nbytes, 0)) > 0) {
            offset += sent;
            nbytes -= sent;
    }

И тогда вы должны быть готовы обрабатывать прерывания во время вызова send () (в этом случае вам просто нужноповторить отправку из той же позиции):

    int offset = 0;
    while ((sent = send(client, file_data + offset, nbytes, 0)) > 0
          || (sent == -1 && errno == EINTR) ) {
            if (sent > 0) {
                offset += sent;
                nbytes -= sent;
            }
    }

В (возможно, редком) случае EINTR, send будет повторяться на следующей итерации цикла и, вероятно, будет иметьшанс завершить в следующий раз и вернуть данные в вашу программу

1 голос
/ 08 апреля 2011
0 голосов
/ 13 марта 2012

проблема была в чтении входящего запроса от клиента.Я не читал это.Если я это сделаю, ничего плохого не случится

0 голосов
/ 08 апреля 2011
// assumes TCP
#define MTU_SIZE 1500
unsigned char mtu[MTU_SIZE];
int bytes_read;

// if you need a header specifing file size send it here

//Read file contents into buffer
while (( bytes_read = fread(mtu, MTU_SIZE, 1, file)) != EOF )
    if ( send(client, mtu, bytes_read, 0) < bytes_read )
        do_error();

Вам не понадобится заголовок, если вы просто отправляете один файл. Вы просто закрываете TCP-соединение, когда закончите отправку, и когда клиент получит EOF, он узнает, что это EOF; -)

Вы также можете найти этот вопрос очень интересным:

Почему запись закрытого TCP-сокета хуже чтения одного?

...