Трабл с WSAEnumNetworkEvents
От: sammy_fr www.khvorov.com
Дата: 29.03.05 08:27
Оценка:
Есть такой кусок кода, основная задача которого транслировать сообщения из ком-порта в сеть и наоборот:
dwError = WaitForMultipleObjects(4, params->hEventsArray, FALSE, INFINITE);
switch (dwError)
{
case WAIT_OBJECT_0: // shutdown event
    TRACE("[ReceiverThread]: Shutdown event\n");

    WSACloseEvent(params->hNetworkEvent);

    closesocket(sockListen);
    WSACleanup();
    bThreadAlive = false;
    bWorking = false;

    break;

case WAIT_OBJECT_0 + 1: // write to COM Port event
    TRACE("[ReceiverThread]: Write to COM Port event\n");

    // write message to serial port;

    break;

case WAIT_OBJECT_0 + 2: // read from COM Port event
    TRACE("[ReceiverThread]: Read from COM Port event\n");

    // read message from serial port

    break;

case WAIT_OBJECT_0 + 3: // async socket event
    if (!WSAEnumNetworkEvents(sockListen, params->hNetworkEvent, &wsaNetworkEvents))
    {
        TRACE("[ReceiverThread]: Async socket event (0x%x): ", wsaNetworkEvents.lNetworkEvents);

        if (wsaNetworkEvents.lNetworkEvents & FD_CONNECT)
        {
            TRACE("FD_CONNECT\n");

            if (!wsaNetworkEvents.iErrorCode[FD_CONNECT_BIT])
            {
                // FD_CONNECT event has occured. Don't serve it
            }
            else
            {
                // error occured
                TRACE("[ReceiverThread]: Error on FD_CONNECT!\n");
            }
        }

        if (wsaNetworkEvents.lNetworkEvents & FD_WRITE)
        {
            TRACE("FD_WRITE\n");

            if (!wsaNetworkEvents.iErrorCode[FD_WRITE_BIT])
            {
                // FD_WRITE event has occured. Don't serve it
            }
            else
            {
                // error occured
                TRACE("[ReceiverThread]: Error on FD_WRITE!\n");
            }
        }

        if (wsaNetworkEvents.lNetworkEvents & FD_READ)
        {
            TRACE("FD_READ\n");

            if (!wsaNetworkEvents.iErrorCode[FD_READ_BIT])
            {
                if (params->LogonStage)
                    iMsgSize = Receiver.NetworkMessageReceive(sockListen, &InBuffer, analyzer.actual_key);
                else
                    iMsgSize = recv(sockListen, (char *) InBuffer, CWS_NETMSGSIZE, 0);

                iMsgSize = ReceiverAnalyze(params, SYSTEM_SERVER, InBuffer, iMsgSize, OutBuffer);
                if (iMsgSize > 0)
                {
                    if (Receiver.NetworkMessageSend(sockListen, OutBuffer, iMsgSize, analyzer.actual_key))
                    {
                        // TODO: Error!
                        TRACE("[ReceiverThread]: NetworkMessageSend() error!\n");
                    }
                }
            }
            else
            {
                // error occured
                TRACE("[ReceiverThread]: Error on FD_READ!\n");
            }
        }

        if (wsaNetworkEvents.lNetworkEvents & FD_CLOSE)
        {
            TRACE("FD_CLOSE\n");

            if (!wsaNetworkEvents.iErrorCode[FD_CLOSE_BIT])
            {
                ::PostMessage(settings->hWnd, WM_TRANSLATETHREAD_MESSAGE, (WPARAM) MSG_STOP_THREAD, (LPARAM) ERROR_CONNECTION_CLOSED);
            }
            else
            {
                // error occured
                TRACE("[ReceiverThread]: Error on FD_CLOSE!\n");
            }
        }
    }

При его работе происходит пошаговое установление соединения с сервером. При этом, при вызове
WSAEnumNetworkEvents, возникает событие при котором lNetworkEvents = 0, хотя такого быть не должно.

Поскажите, плиз, где здесь косяк

Вот кусок лога, взятого при отладке программы:
[ReceiverThread]: Thread started!
[CSerialPort] COM port: COM1, def string: baud=9600 parity=N data=8 stop=1
[CSerialPort] Initialization for COM port 1 completed
'CSTranslator.exe': Loaded 'C:\WINNT\system32\msafd.dll', Cannot find or open a required DBG file.
'CSTranslator.exe': Loaded 'C:\WINNT\system32\wshtcpip.dll', Cannot find or open a required DBG file.
[ReceiverThread]: Async socket event (0x13): FD_CONNECT
FD_WRITE
FD_READ
[ReceiverAnalyze]: Received hash key
[ReceiverThread]: Async socket event (0x1): FD_READ
[ReceiverAnalyze]: MSG_LOGIN_ACK received
[ReceiverThread]: Async socket event (0x0): [ReceiverThread]: Async socket event (0x20): FD_CLOSE
Got message from thread! wParam = 0x0, lParam = 0x2
[ReceiverThread]: Shutdown event
'CSTranslator.exe': Unloaded 'C:\WINNT\system32\wshtcpip.dll'
[CSerialPort]: destructor


Спасибо, Дима
Regards,
Dmitry
khvorov.com
Re: Трабл с WSAEnumNetworkEvents
От: butcher Россия http://bu7cher.blogspot.com
Дата: 29.03.05 10:42
Оценка:
Здравствуйте, sammy_fr, Вы писали:

_>Есть такой кусок кода, основная задача которого транслировать сообщения из ком-порта в сеть и наоборот:

_>
dwError = WaitForMultipleObjects(4, params->hEventsArray, FALSE, INFINITE);
_>if (!WSAEnumNetworkEvents(sockListenх, params->hNetworkEvent, &wsaNetworkEvents))
_>    }


В выделенном точно нужный дескриптор передаётся?

Нет ничего невозможного..
Re[2]: Трабл с WSAEnumNetworkEvents
От: sammy_fr www.khvorov.com
Дата: 29.03.05 12:26
Оценка:
Здравствуйте, butcher, Вы писали:

B>В выделенном точно нужный дескриптор передаётся?


Все точно, дескриптор нужный. Проблема уже решена и она заключалась в том, что функция Receiver.NetworkMessageReceive, которая получает сообщение, делала это в два этапа. Сначала читалось N байт из сокета, а потом все остальное. В результате, после первого чтения взводилось 3-е событие, которое отвечало за асинхронный ввод-вывод через сокет. Это приводило к неправильному срабатыванию WaitForMultipleObjects и WSAEnumNetworkEvents возвращала 0. Решение — делать ResetEvent для третьего события сразу после чтения из сокета (вызова recv).

Но, все равно спасибо

Дима
Regards,
Dmitry
khvorov.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.