Добавление пользовательского заголовка сообщения - PullRequest
0 голосов
/ 01 марта 2012

Может кто-нибудь сказать мне: "Как построить заголовок?"Я пишу код клиент-сервер FTP.И я хочу добавить заголовок на стороне клиента для всех пакетов данных, которые я должен отправить на сервер с информацией, такой как размер моих данных и т. Д.

Я видел несколько примеров в SO, но не могу понятьТочный путь.Будем благодарны за любые указатели на пример / пример кода.

Ответы [ 3 ]

1 голос
/ 01 марта 2012

Лучший способ создать данные протокола - это иметь где-то буфер uint8_t и заполнять его, как указано в протоколе.

Для собственно FTP это довольно просто, поскольку существуют только ASCIIСтроки в контрольном соединении.Примерно так может работать:

bool append_literal(uint8_t **cursor, uint8_t *end, uint8_t const *data, size_t size) {
    assert(cursor);
    assert(*cursor);
    assert(end);
    assert(*cursor < end);
    assert(data);
    if((end - *cursor) < size)    // Check buffer limit
        return false;
    memcpy(*cursor, data, size);  // Copy
    *cursor += size;              // Increment cursor
    return true;
}

bool append_number(uint8_t **cursor, uint8_t *end, uint64_t number) {
    assert(cursor);
    assert(*cursor);
    assert(end);
    assert(*cursor < end);
    if((end - *cursor) < 17)     // Max number of base 10 digits in uint64_t
        return false;
    *cursor += sprintf(*cursor, "%" PRIu64, number);
    return true;
}

bool append_uint32_binary(uint8_t **cursor, uint8_t *end, uint32_t value) {
    assert(cursor);
    assert(*cursor);
    assert(end);
    assert(*cursor < end);
    if((end - *cursor) < 4)      // Bytes needed for uint32 value
        return false;
    *(*cursor)++ = (value >> 24) & 0xff;
    *(*cursor)++ = (value >> 16) & 0xff;
    *(*cursor)++ = (value >> 8) & 0xff;
    *(*cursor)++ = value & 0xff;
    return true;
}

// Specific FTP commands
bool append_size_command(uint8_t **cursor, uint8_t *end, uint64_t size) {
    return append_literal(cursor, end, "SIZE ", 5) &&
        append_number(cursor, end, size) &&
        append_literal(cursor, end, "\r\n", 2);
}
// [...]

bool send_size_command(int fd, uint64_t size) {
    uint8_t buffer[32];
    uint8_t *cursor = buffer;
    uint8_t *const end = buffer + sizeof buffer;
    if(!append_size_command(&cursor, end, size))
        return false;
    size_t length = cursor - buffer;
    ssize_t sent = send(fd, buffer, length, 0);
    return (sent == length);
}

Операторы "assert" проверяют вещи, которые всегда будут верными, если ваша программа написана правильно, то есть указатели действительны.Любая функция возвращает true в случае успеха и false в случае неудачи.

Я использовал стандартные функции POSIX для сокетов, потому что WinSock их реализует, и они довольно переносимы.

Ваша домашняя работа - найти заголовки, которые вам нужно включить для PRIu64:)

1 голос
/ 01 марта 2012

Проверьте scapy, библиотеку для создания пакетов. Я думаю, это то, что вам нужно.

0 голосов
/ 02 марта 2012

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

typedef struct  
{
    DWORD   dwMsgType ; 
    DWORD   dwMsgSize ;
}MSG_HEADER, *PMSG_HEADER ;
...