Как мне создать свой собственный пакет для отправки через UDP? - PullRequest
3 голосов
/ 10 апреля 2011

Я делаю свое собственное клиент-серверное приложение на C, которое реализует протокол TFTP.После прочтения RFC TFTP и создания простого клиент-серверного приложения на сокете, я немного запутался в том, как создавать конкретные пакеты, которые должны быть созданы для протокола TFTP.

Например,Пакет WRQ должен быть таким:

        2 bytes     string    1 byte     string   1 byte
        ------------------------------------------------
       | Opcode |  Filename  |   0  |    Mode    |   0  |
        ------------------------------------------------

, который извлекается из официального RFC.

У меня есть .h, в котором я определяю все структуры для пакетов, но я 'я не уверен, что я делаю правильно, и мне не повезло, что я нашел информацию в Интернете.

Структура, которую я создал для этого пакета:

    struct WRQ {
      signed short int opcode; //2 bytes
      char * filename; // N bytes
    char zero_0; // 1 byte
      char * mode; // N Bytes
    char zero_1; // 1 byte
    };

У меня два сомнения:

а) когда я делаю sizeof (struct WRQ), он возвращает 20 байтов.Который не тот размер, который я хочу получить.Почему это происходит?

б) Как мне определить строки?потому что я хочу, чтобы сервер сам получал строку, и, я думаю, таким образом, он получит указатель на строку на клиентском компьютере.

Я надеюсь, что все ясно, и вы могли бы помочь мне, потому чтоЯ застрял на данный момент!

Ответы [ 4 ]

2 голосов
/ 10 апреля 2011

Следующий код (без проверки ошибок) является одним из возможных способов создания пакета и его отправки.Обратите внимание, что предполагается, что и filename, и mode не равны NULL.Я не знаю, является ли это верным предположением или нет.Даже если это так, было бы целесообразно проверить NULL, прежде чем использовать их в реальном коде:

struct WRQ *p;
int packetLen;
char *buf;
char *pos;
int ret;

// compute packet length.  Start with fixed size data
packetLen = sizeof( p->opcode ) + sizeof( p->zero_0 ) + sizeof( p->zero_1 );
// This assumes (possibly incorrectly) that filename and mode are not null
packetLen += strlen( p->filename ) + 1;
packetLen += strlen( p->mode ) + 1;

// allocate the buffer
buf = malloc( packetLen ); 
pos = buf;

// and start filling it in
// I am assuming (but didn't study the RFC that it should be network byte order)
*(signed short int*)pos = htons( p->opcode );
pos += sizeof( p->opcode );
strcpy( pos, p->filename );
pos += strlen( p->filename ) + 1;
*pos = p->zero_0;
strcpy( pos, p->mode );
pos += strlen( p->mode ) + 1;
*pos = p->zero_1;

ret = send( s, buf, packetLen, flags );

free( buf );
1 голос
/ 10 апреля 2011

В вашем коде char * filename; - указатель на символ. Это означает, что filename занимает только 4 байта. Даже если длина вашей строки составляет 1000 байт, поскольку filename является просто указателем, он просто содержит 4-байтовый адрес памяти первого символа вашей строки.

Итак, у вас есть два решения: используйте char filename[MAX_LENGTH], чтобы объявить строку размером MAX_LENGTH и всегда передавать ее. Или вы можете включить другое поле, скажем, «filename_length», которое сообщает вам, сколько байтов ожидать при прочтении поля имени файла.

(Вышеприведенное на самом деле неверно. filename не может быть длиной 4 байта. Имя файла будет sizeof(char*) длиной. Это, вероятно, 4 байта на вашем компьютере. Но указатели не всегда 4 байта, и в настоящее время люди Это связано с большими трудностями, связанными с принятием 4-байтового указателя на 64-битных архитектурах. Поэтому я просто говорю. Не принижайте меня.)

Чтобы ответить на ваш второй вопрос - почему sizeof () 20 байт? Компилятор будет дополнять фрагменты структуры дополнительными байтами, чтобы каждый элемент помещался в 4-байтовую границу. Компилятор может эффективно работать со «словами», а не со структурами странного размера. (Опять же, «4» зависит только от архитектуры. Каждая архитектура имеет свою длину «слова».) Это называется выравниванием. Существует отличный поток SO, который дает более подробную информацию: Почему sizeof для структуры не равен сумме sizeof каждого члена?

1 голос
/ 10 апреля 2011

Вы не можете просто поместить туда char* и ожидать, что он сработает, потому что это указатель, и вам нужны фактические символьные данные для появления в пакете (указатель, передаваемый между двумя программами, почти никогда не будет работать!),Поскольку файловая часть пакета имеет переменную длину, вы не можете представить весь пакет как структуру, как пытаетесь это сделать.Вместо этого вам, вероятно, следует динамически генерировать пакет, объединяя части по требованию, например, с помощью функции, имеющей эту подпись:

vector<char> makePacket(uint16_t opcode, const char* filename, const char* mode);
0 голосов
/ 10 апреля 2011

C структуры не могут иметь переменный размер.Вам придется определить «имя файла» и «режим» как char field_name [preset size]; или создать структуру вручную в буфере памяти во время выполнения.

Наконец, если вам нужна реализация TFTP в C,Вы можете поспорить, что кто-то написал, если уже.Например, BSD-файл tftp-hpa используется в различных дистрибутивах Linux.

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