Hey everyone, I'm having some trouble using WaitForMultipleObjects to wait for incoming connections (which I would later accept()).
My code simply uses one thread to start listening, and then uses the main thread to try to connect to it.
Code:
// Main Thread
int main() {
WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData))
assert(false);
pthread_t mynewthread;
pthread_create(&mynewthread, NULL, threadMain, NULL);
// Wait for the listener thread to be ready
Sleep(2000);
// Now try to connect to the thread via tcp
SOCKET socket = ::socket(AF_INET, SOCK_STREAM, 0);
struct hostent *hp = gethostbyname("127.0.0.1");
assert(hp);
struct sockaddr_in server;
server.sin_family = AF_INET;
memcpy(&server.sin_addr.s_addr, hp->h_addr, hp->h_length);
server.sin_port = htons(1337);
if (::connect(socket, (const sockaddr *)&server, sizeof(server))) {
std::cout << GetLastErrorMessage(GetLastError()) << std::endl;
assert(false);
}
cout << "connected successfully!" << endl;
}
Code:
// Listener Thread
HANDLE getEventAndEnableNonblockingMode(SOCKET socket) {
HANDLE socketEventHandle = WSACreateEvent();
WSAEventSelect(socket, socketEventHandle, FD_ACCEPT | FD_READ | FD_CLOSE);
return socketEventHandle;
}
void closeEventAndDisableNonblockingMode(SOCKET socket, HANDLE socketEventHandle) {
// We need to close it here because having an event
// open puts the socket in non-blocking mode. we need it to be in blocking mode for
// things like accept().
WSACloseEvent(socketEventHandle);
WSAEventSelect(socket, NULL, 0);
// Now we make it blocking.
unsigned long resultBuffer = 0;
unsigned long resultBufferBytesWritten = 0;
unsigned long newNonblockingEnabled = 0;
int error = WSAIoctl(socket, FIONBIO, &newNonblockingEnabled, sizeof(unsigned long), &resultBuffer, sizeof(resultBuffer), &resultBufferBytesWritten, NULL, NULL);
assert(error == 0);
}
void *threadMain(void *args) {
SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
assert(listenSocket >= 0);
struct sockaddr_in name;
name.sin_family = AF_INET;
name.sin_addr.s_addr = htonl(INADDR_ANY);
name.sin_port = htons(1337);
int nameStructLength = sizeof(name);
if (bind(listenSocket, (struct sockaddr *)&name, nameStructLength)) {
int error = GetLastError();
std::cout << "Error in connection listener: " << GetLastErrorMessage(error) << std::endl;
}
HANDLE socketEventHandle = getEventAndEnableNonblockingMode(listenSocket);
HANDLE events[1] = { socketEventHandle };
DWORD result = WaitForMultipleObjects(1, events, false, INFINITE);
closeEventAndDisableNonblockingMode(listenSocket, socketEventHandle);
if (result == WAIT_OBJECT_0) {
}
else {
assert(false);
}
cout << "wfmo returned!" << endl;
return NULL;
}
Any idea why WaitForMultipleObjects isnt waiting for connections like listen() would?
Thanks!
PS. I need to use WaitForMultipleObjects because soon I will be waiting on more than just the socket, I'll need to respond to a number of other events as well.