Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как работать по сети в C Builder?
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
GL_basik
Мне здесь пришлось писать интерфейс для сетевого монитора. Вообщем теперь осваиваю winsock. И в связи с этим у меня возникли вопросы.
Девайс конфигурируется и передает служебную информацию по UDP. Мне соответсвенно необходимо принимать пакеты посланые этим девайсом. Но протокол UDP это протокол без установки соединения. Соответственно пакет от устройства может придти в любой момент времени. В Winsock я не нашел что либо похожее на прерывание или событие происходящще по поступлению нового пакета. Есть лишь процедура recv, которая, собственно, осуществляет прием данных. Вопрос в следующем, как определить пришел мне пакет или нет? Или может быть это не надо? Вообщем как принять данные по протоколу UDP?
and_pp
См. функцию WSAAsyncSelect - она позволяет назначить сообщение при приходе очередного пакета.

Вот как это сделано у меня:
Код
void SetEvent(HWND Handle, unsigned int wMsg, long lEvent=FD_READ) {
        WSAAsyncSelect(UDPSocket,Handle,wMsg,lEvent);
    };


Далее в описании класса формы описываешь обработку сообщения:
Код
BEGIN_MESSAGE_MAP
    VCL_MESSAGE_HANDLER(0x8F10, TMessage, Mes);
END_MESSAGE_MAP(TForm);

   __fastcall void Mes(TMessage ms);


Где 0x8F10 - произвольные код сообщения. Может быть лубым, гдавное, чтобы не совпал с предопределенным системным

Ну а в самой программе пишешь как обычно
Код
void __fastcall TFrmOSC::Mes(TMessage Msg)
{
        int addr_len = sizeof(remote_addr);
        int res = recvfrom(UDPSocket,data,len,0,(struct sockaddr FAR*)&remote_addr, (int FAR*)&addr_len);
        addr = remote_addr.sin_addr.S_un.S_addr;
        port = htons((u_short)remote_addr.sin_port);
        int err = WSAGetLastError();

     * * *
}


Еще один совет. По умолчанию, размер входного буфера в Windows для сокета равен 8192 байта. Если пакеты будут сыпаться слишком часто, они будут теряться. Лучше всего установить размер буфера побольше. Вот мой кусок кода

Код
bool Stoika::SetRxBufferSize(unsigned int bufferSize)
{
   if (bufferSize <= 0) return false;
   unsigned int oldBufferSize = GetRxBufferSize();
   if (setsockopt(UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(bufferSize)) < 0)
   {
        setsockopt(UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&oldBufferSize, sizeof(oldBufferSize));
        return false;
   }
   return true;
}  // end Stoika::SetRxBufferSize()

unsigned int Stoika::GetRxBufferSize()
{
    unsigned int rxBufferSize = 0;
    int len = sizeof(rxBufferSize);
    if (getsockopt(UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&rxBufferSize, &len) < 0)
    {
        return 0;
    }
    return ((unsigned int)rxBufferSize);
}  // end Stoika::GetRxBufferSize()
subver
А не проще бросить на форму компонент типа TNMUDP и работать по его событиям? в билдере вроде как давно уже есть наборчик компонентов для этого дела.
and_pp
У родных UDP компонентов билдера есть один общей недостаток - уж очень они любят терять пакеты.
std.denis
для CBuilder, Delphi и .NET есть же замечательная библиотека - Indy.Sockets..
очень даже работоспособна
Sot
Цитата(GL_basik @ Aug 31 2006, 18:54) *
Мне здесь пришлось писать интерфейс для сетевого монитора. Вообщем теперь осваиваю winsock. И в связи с этим у меня возникли вопросы.
...
Вообщем как принять данные по протоколу UDP?

Есть хорошее руководство от Beej, перевод здесь:
http://www.wasm.ru/print.php?article=socketbybeej

После прочтения многие вопросы пропадут.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.