Вот метод класса (все методы и переменные объявлены общедоступными). ПРИМЕЧАНИЕ. DiscoverWinsockLib выполняет WSAStartup, и я знаю, что эта часть работает.Он также выполняет LoadLibrary и находит точки входа DLL для перечисленных ниже функций, переименованный с префиксом lpfn_.
Независимо от того, что я делаю, я не могу решить, почему я получаю условие ошибки при работе сокета наnon-socket в теме.
Любая помощь будет принята с благодарностью.
bool __fastcall TRANSPORT::Establish (const char *host, int port, int timeout)
{
bool rFlag;
int rval;
rFlag = false;
DiscoverWinsockLib();
if( WSH )
{
hostEntry = gethostbyname(host);
if( !hostEntry )
{
LastErrorCode = lpfn_WSAGetLastError();
lpfn_WSACleanup();
SetErrorMsg();
}
else
{
CSocket = lpfn_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (CSocket == INVALID_SOCKET)
{
LastErrorCode = lpfn_WSAGetLastError();
SetErrorMsg();
lpfn_WSACleanup();
}
else
{
RxDataBuf.len = RXDATA_BUFSIZE;
RxDataBuf.buf = RxBuffer;
RxOverlapped.hEvent = lpfn_WSACreateEvent();
if(RxOverlapped.hEvent == WSA_INVALID_EVENT)
{
LastErrorCode = lpfn_WSAGetLastError();
SetErrorMsg();
SocketShutdown();
//lpfn_closesocket(CSocket);
}
else
{
if(lpfn_WSAEventSelect(CSocket, RxOverlapped.hEvent, FD_ALL_EVENTS) == SOCKET_ERROR)
{
LastErrorCode = lpfn_WSAGetLastError();
SetErrorMsg();
lpfn_closesocket(CSocket);
lpfn_WSACloseEvent(RxOverlapped.hEvent);
}
else
{
hThreadIO = CreateThread(0, 0, ProcessEvents, (void *)this, 0, &ThreadID);
// Try to connect to the server
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
serverInfo.sin_port = htons(port);
if( lpfn_connect(CSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr)) == SOCKET_ERROR )
{
LastErrorCode = lpfn_WSAGetLastError();
if( LastErrorCode != WSAEWOULDBLOCK )
{
SetErrorMsg();
SocketShutdown();
}
else
rFlag = true;
}
else
rFlag = true;
}
}
}
}
}
return(rFlag);
}
А вот упомянутая выше тема:
DWORD WINAPI ProcessEvents(void *pParam)
{
TRANSPORT *T;
WSANETWORKEVENTS NetEvents;
DWORD EIndex;
DWORD rc;
bool Failure;
T = (TRANSPORT *)pParam;
Failure = false;
do
{
EIndex = T->lpfn_WSAWaitForMultipleEvents( 1, &T->RxOverlapped.hEvent, false, 3000, true );
if( EIndex == WSA_WAIT_FAILED )
{
T->LastErrorCode = T->lpfn_WSAGetLastError();
T->SetErrorMsg();
Failure = true;
}
if( EIndex == WSA_WAIT_TIMEOUT )
{
if( T->OnConnectTimeout )
T->OnConnectTimeout(T);
Failure = true;
}
}while( EIndex != WAIT_IO_COMPLETION && !Failure );
if( Failure )
return(EIndex);
// Get the event(s) that occurred and their associated error array
if(T->lpfn_WSAEnumNetworkEvents(T->CSocket, T->RxOverlapped.hEvent, &NetEvents) == SOCKET_ERROR)
{
T->LastErrorCode = T->lpfn_WSAGetLastError();
T->SetErrorMsg();
return(EIndex);
}
// =================================================================
// Code above fetches the event that woke this thread up
// Code below deals with the events as they are detected
// =================================================================
if( NetEvents.lNetworkEvents & FD_CONNECT )
{
if( T->OnConnect )
T->OnConnect(T);
T->lpfn_WSAResetEvent(T->RxOverlapped.hEvent);
}
else if( ( NetEvents.lNetworkEvents & FD_READ) )
{
rc = T->lpfn_WSARecv(T->CSocket, &T->RxDataBuf, 1, &T->RxBytes, &T->Flags, &T->RxOverlapped, NULL);
EIndex = T->lpfn_WSAGetLastError();
if( (rc == SOCKET_ERROR) && (EIndex != WSA_IO_PENDING || EIndex != WSAEWOULDBLOCK ) )
{
T->LastErrorCode = EIndex;
T->SetErrorMsg();
}
else
{
rc = T->lpfn_WSAWaitForMultipleEvents(1, &T->RxOverlapped.hEvent, true, INFINITE, true);
if(rc == WSA_WAIT_FAILED)
{
T->LastErrorCode = T->lpfn_WSAGetLastError();
T->SetErrorMsg();
}
else
{
rc = T->lpfn_WSAGetOverlappedResult(T->CSocket, &T->RxOverlapped, &T->RxBytes, false, &T->Flags);
if(!rc)
{
T->LastErrorCode = T->lpfn_WSAGetLastError();
T->SetErrorMsg();
}
else
{
if( T->RxBytes > 0 && T->OnReceive )
T->OnReceive(T);
T->lpfn_WSAResetEvent(T->RxOverlapped.hEvent);
}
}
}
}
return(rc);
}
** ОБНОВЛЕНИЕ **Я обнаружил, что вызов EIndex = T-> lpfn_WSAWaitForMultipleEvents (1, & T-> RxOverlapped.hEvent, false, 3000, true);внутри функции Thread возвращается WSA_WAIT_FAILED
И если я отключаю функцию потока и проверяю возвращаемое значение lpfn_WSAWaitForMultipleEvents, вне потока сразу после вызова соединения я получаю действительное возвращаемое значение WSAEWOULDBLOCK.
Думая, что у меня может быть проблема с получением адреса изнутри потока, я изменил код потока следующим образом:
DWORD WINAPI ProcessEvents(void *pParam)
{
...
WSAEVENT events[1];
T = (TRANSPORT *)pParam;
Failure = false;
do
{
events[0] = T->RxOverlapped.hEvent;
EIndex = T->lpfn_WSAWaitForMultipleEvents( 1, events, false, 3000, true );
....
и мне все еще не удается сделать WSAWaitForMultipleEvents счастливым!
какие-либо мысли / предложения по этому поводу?