Есть такой кусок кода, основная задача которого транслировать сообщения из ком-порта в сеть и наоборот:
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
Спасибо, Дима
Здравствуйте, sammy_fr, Вы писали:
_>Есть такой кусок кода, основная задача которого транслировать сообщения из ком-порта в сеть и наоборот:
_>dwError = WaitForMultipleObjects(4, params->hEventsArray, FALSE, INFINITE);
_>if (!WSAEnumNetworkEvents(sockListenх, params->hNetworkEvent, &wsaNetworkEvents))
_> }
В выделенном точно нужный дескриптор передаётся?
Здравствуйте, butcher, Вы писали:
B>В выделенном точно нужный дескриптор передаётся?
Все точно, дескриптор нужный. Проблема уже решена и она заключалась в том, что функция Receiver.NetworkMessageReceive, которая получает сообщение, делала это в два этапа. Сначала читалось N байт из сокета, а потом все остальное. В результате, после первого чтения взводилось 3-е событие, которое отвечало за асинхронный ввод-вывод через сокет. Это приводило к неправильному срабатыванию WaitForMultipleObjects и WSAEnumNetworkEvents возвращала 0. Решение — делать ResetEvent для третьего события сразу после чтения из сокета (вызова recv).
Но, все равно спасибо
Дима