I'm trying to write a simple server application using Winsock2. I have a socket listening on port 80 (for http traffic). When I run the program and use my browser to connect to 127.0.0.1, the server receives the connection and displays it as expected.
New Connection
Recieved message:
GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
DNT: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
The problem comes when I try to close the socket. I'm using the following two commands:
closesocket(currentSocket);
FD_CLR(currentSocket, &socketList);
When I do this, the program keeps repeating the output as if it was getting the same request over and over. If I remove either of these commands it only displays the output once, as it should.
The complete source code is as follows. This is a simplified version of the code that will duplicate the behavior, so I've omitted certain checks for clarity.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // !WIN32_LEAN_AND_MEAN
#pragma comment(lib, "ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
void runTest()
{
////// SETUP ///////
const int LISTENING_PORT = 80;
const int BUFFER_SIZE = 4098;
WSADATA wsa;
sockaddr_in listeningAddress;
listeningAddress.sin_family = AF_INET;
listeningAddress.sin_port = htons(LISTENING_PORT);
listeningAddress.sin_addr.S_un.S_addr = INADDR_ANY;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET listeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(listeningSocket, (sockaddr*)&listeningAddress, sizeof(listeningAddress));
listen(listeningSocket, SOMAXCONN);
fd_set socketList;
FD_ZERO(&socketList);
FD_SET(listeningSocket, &socketList);
////// MAIN LOOP ///////////
bool isRunning = true;
while(isRunning) // endless loop, normally has interupt mechanism
{
fd_set socketListCopy = socketList;
int socketCount = select(0, &socketListCopy, nullptr, nullptr, nullptr);
for (int i = 0; i < socketCount; i++)
{
SOCKET currentSocket = socketListCopy.fd_array[i];
if (currentSocket == listeningSocket)
{
std::cout << "New Connection\n";
SOCKET client = accept(listeningSocket, nullptr, nullptr);
FD_SET(client, &socketList);
}
else
{
char buffer[BUFFER_SIZE];
memset(buffer, 0, BUFFER_SIZE);
int bytesIn = recv(currentSocket, buffer, BUFFER_SIZE, 0);
std::cout << "\nRecieved message:\n" << buffer << '\n';
// Using the following two lines causes the output to loop
closesocket(currentSocket);
FD_CLR(currentSocket, &socketList);
}
}
}
WSACleanup();
}