Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ассинхронная работа socket'ов WinSock2, Неблокирующее чтение через WSARecvFrom() 
V
    Опции темы
VID
Дата 5.7.2006, 08:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 4.10.2004
Где: Новосибирск

Репутация: нет
Всего: нет



 Привет!
 Появилась проблема с чтением данных с сокета, в режиме SOCK_DGRAM (без соединения) через функцию WSARecvFrom. Я читаю с указанием адреса процедуры завершения, которая должна будет вызваться системой при окончании приема датаграммы, но не вызывается  smile .
 Может кто сталкивался с подобной проблемой. MSDN примеров на эту тему не дает, инет тоже не кишит подобной информацией.
 Ниже привожу код, что и как вызывается. Прога - консольное приложение, далее планируется всю начинку запихнуть в dll

Код

#include "stdafx.h"
#include "winsock2.h"

WSADATA m_wsaData;
SOCKET sckt;
in_addr s;
sockaddr_in socketAddress, recvAddr;
WSABUF recvBuf;
WSAOVERLAPPED overlapped;
char buf[1024];

void CALLBACK CompletionRoutine(DWORD dwError, DWORD dwTransfered, LPWSAOVERLAPPED overlapped, DWORD dwFlags)
{
    // Processing received DHCP message;
    cout << "Gets a message on Client UDP port number of: " << 68 << endl;
    cout << "Received bytes number: " << dwTransfered << endl;
    cout << "Received buffer: " << recvBuf.buf << endl;
}

int main(int argc, char* argv[])
{
    // Check out socket asynchronous operation with CompletionRoutine
    {
    // Инициализируем WinSock2
        int iResult = WSAStartup(WINSOCK_VERSION, &m_wsaData);
        if (iResult != NO_ERROR)
        {
            cout << "Error at WSAStartup()" << endl;
            return 0;
        }

        // Создаем SOCKET об'ект
        sckt = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);

        // Enable broadcast address and allow other process binds to the same port.
        BOOL bOptVal = TRUE;
        int bOptLen = sizeof(BOOL);
        if (setsockopt(sckt, SOL_SOCKET, SO_BROADCAST, (char*)&bOptVal, bOptLen) == SOCKET_ERROR)// ||
            //setsockopt(sckt, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen) == SOCKET_ERROR)
        {
            cout << "Error occur while set up socket options!!!" << endl;
            return -1;
        }

        // Set up the sockaddr structure.
        socketAddress.sin_family = AF_INET;
        socketAddress.sin_addr.s_addr = inet_addr("Мой Ip адрес");
        socketAddress.sin_port = htons(68); // Слушаем порт 68
        
        if (bind(sckt,(SOCKADDR*) &socketAddress, sizeof(socketAddress) ) == SOCKET_ERROR)
        {
            cout << "Error occur while bind socket!!!" << endl;
            return -1;
        }

        DWORD recvBytesNumber = 0,
              flags = 0;
        int fromLen = sizeof(recvAddr);
        overlapped.hEvent = NULL;
        recvBuf.buf = buf;
        recvBuf.len = 1024;
        int rc = WSARecvFrom(sckt, &recvBuf, 1, &recvBytesNumber, &flags, (SOCKADDR*) &recvAddr,
            &fromLen, &overlapped, &CompletionRoutine);
        if (rc == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSA_IO_PENDING)
            {
                cout << "Wait until data arrived" << endl;
            }
            else
            {
                cout << "Error occure while listening port 68" << endl;
                return -1;
            }
        }
        else
        {
            cout << "Gets a message on Client UDP port number of: 68" << endl;
            cout << "Received buffer: " << recvBuf.buf << endl;
        }
    }
    closesocket(sckt);
    WSACleanup();
    return 0;
}


Далее в другом месте посылаем сообщение в порт 68.
В блокирующем режиме я его получаю, а в неблокирующем функция обратного вызова CompletionRoutine не вызывается  smile Почему? 
PM MAIL   Вверх
maxim1000
Дата 5.7.2006, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 2
Всего: 110



а где происходит ожидание прочтения?
а то он только начал читать, а программа переходит на closesocket, WSACleanup и вообще завершает процесс... 


--------------------
qqq
PM WWW   Вверх
VID
Дата 5.7.2006, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 4.10.2004
Где: Новосибирск

Репутация: нет
Всего: нет



Мда, тут я урезал программку, поэтому некрасиво получилось, грубо говоря там бесконечный цикл перед закрытием сокета, то есть примерно так:
Код

char value = 0; // Переменная для служебных целей
bool exit = false;
while(!exit)
{
     value = getchar();
     switch(value)
     {
          case '1': // и так далее
          case '5' exit = true; break;
     }
}
closesocket(socket);


Примерно так это выглядит, на деле сложнее, но суть не меняется я просто ожидаю. Делал и в отдельном потоке прослушивание совета и т.д и т.п, но результат один. 
PM MAIL   Вверх
maxim1000
Дата 5.7.2006, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 2
Всего: 110



на самом деле всё именно зависит от того, как ждать
если бы Windows прерывала поток в любом месте и выполняла бы CompletionRoutine, наверняка, рано или поздно бы произошёл сбой - никакой ведь синхронизации
поэтому делается по-другому:
процедура окончания вызывается только, если поток находится в прерываемом состоянии
для этого можно использовать, например, функцию SleepEx 


--------------------
qqq
PM WWW   Вверх
VID
Дата 5.7.2006, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 4.10.2004
Где: Новосибирск

Репутация: нет
Всего: нет



maxim1000 спасибо, на самом деле так и оказалось. Я и думать забыл про синхронизацию  smile 
Спасибо. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0602 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.