2011-01-15 4 views
0

Я пытаюсь сделать простой клиент DHCP. Он должен отправить сообщение на сервер DHCP (уже есть), получить сообщение обратно и проанализировать его. Я создалDHCP over UDP отправка вопроса

-структуру
struct dhcp_msg{ 
_int8 op; //opcode 
_int8 htype; //hardware type 
_int8 haddr; //hardware adress 
_int8 hops; //hop count 

_int32 tid; //transaction id 

_int16 sec; //seconds 
_int16 unused; //unused 

_int32 cipaddr; //client ip 
_int32 yipaddr; //your ip 
_int32 sipaddr; //server ip 
_int32 gipaddr; //gateway ip 

char chaddr[16]; //client hardware address 
char sname[64]; //server name 
char bname[128]; //boot file name 

_int8 mcookie[4]; //magic cookie 
}; 

Если я заполнить все поля по данным, как отправить это с SendTo()? Должен ли я разобрать его на char и отправить указатель, поскольку sendto() запрашивает указатель в качестве второго параметра.

char *buffer; 
...? 
sendto(socketC, buffer, sizeof(buffer), 0, (SOCKADDR *)&servAddr, sizeof(sockaddr_in)); 

Как отправить сообщение?

ответ

4

Прежде всего, вы должны сказать своему компилятору, чтобы он не добавлял никаких прокладок в структуры. И тогда вы можете сделать:

struct dhcp_msg my_msg; 
// Fill my_msg 
sendto(socket, (void *) &my_msg, ...) 

UPDATE

В Linux и Windows, sendto функция немного отличается, как мы выяснили, в комментариях к этому ответу. Поэтому мы должны использовать преобразования (void *) и (char *) для Linux и Windows соответственно.

О порядке байт: вы должны быть также осторожными. Но он должен работать отлично для всех процессоров x86. Единственная «неправильная» система в стиле endian, которую я когда-либо использовал, была суперкомпьютером на базе IBM Power6.

+0

Почему приведение типов в 'void *'? – ulidtko

+0

из-за http://linux.die.net/man/2/sendto – Elalfer

+2

@Elalfer: нет необходимости бросать в void *; преобразование неявно. –

1

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

struct dhcp_msg msg; 
// fill in all fields... 
sendto(socketC, &msg, sizeof(struct dhcp_msg), ...); 

Длина вашего сообщения будет sizeof(struct dhcp_msg).

И не забывайте, что ваш компилятор может добавить в структуру padding bytes, поэтому его размер может стать больше, чем вы ожидаете.

+0

вам нужно быть осторожным со структурой padding – Elalfer

+0

, которая была моей первой идеей, но я получаю ошибку C2664: 'sendto ': невозможно преобразовать параметр 2 из' dhcp_msg * 'в' const char * ' – gemexas

+0

@gemexas Хмм. Затем попробуйте явное typecasting, '(void *) msg'. – ulidtko

-2

отдать свой STRUCT dhcp_msg в полукокса *

+0

'struct dhcp_msg *' возможно. – ulidtko

+1

почему даже char *? – Elalfer

0

Позвольте мне начать новый ответ, как и другие слишком много замечаний, которые трудно закопать.

Проблема, которая OP действительно имеет тип-указатель ошибка преобразования: MSVC отказывается передать struct dhcp_msg* как аргумент const char*, и никакие явные преобразования не помогают.

#include <sys/socket.h> 

struct test { 
    int a; 
    int b; 
}; 

int main() { 
    struct test t; 
    t.a = 3; 
    t.b = 5; 
    send(1, &t, sizeof(struct test), 0); 

    return 0; 
} 

Этот источник не предназначен для запуска, но компилирует штраф с моей GCC 4.4.5 (а также void* и char* варианты типажей).

Хорошо, проблема решена путем тщательного приведения типов.

+0

Я наконец-то запустил его. sendto (socketC, (const char *) & msg, ... – gemexas

+0

спасибо за помощь :) – gemexas

+0

@gemexas принимает ответ, если он был полезен ';)' – ulidtko