To force the listening thread terminate in a safe way I made the boolean m_bIsShuttingDownflag known to both main and listening thread. In addition, my main thread knows the port m_sLocalPort listening thread listens to. Pressing shutdown button makes the main thread set this flag to TRUE, connect to the port just to make listening thread exit the listen() function. Immediately after accept() the m_bIsShuttingDownflag is checked, and if it is set, the listening loop exits, the listening socket m_listen_socket is closed, and whatever resources being used by the listening thread are released. This way you should not wait for the next connection to make your server shutdown, because you provoke its shutdown by making the last connection yourself from the main thread.
Important: in the main thread you should wait on the listening thread's handle m_hListeningThread in case the main thread is going to be shut down as well. If you don't synchronize, you risk to crash your app.
The code snippet:
----The main thread------
Code:
CloseListeningThread();
where the function CloseListeningThread() is defined like:
Code:
int CloseListeningThread()
{
int iRetVal = SOCKET_ERROR;
if(m_hListeningThread)
{
// Convert nnn.nnn address to a usable one
unsigned int addr = inet_addr("127.0.0.1");
struct hostent *hp = gethostbyaddr((char *)&addr,4,AF_INET);
if (hp != NULL )
{
struct sockaddr_in proxy; // server's address structure
memset(&proxy,0,sizeof(proxy));
memcpy(&(proxy.sin_addr),hp->h_addr,hp->h_length);
proxy.sin_family = hp->h_addrtype;
proxy.sin_port = htons(m_sLocalPort);
m_bIsShuttingDown = TRUE; // tell the listening thread it is going to be terminated
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if(INVALID_SOCKET != s)
{
iRetVal = connect(s,(struct sockaddr*)&proxy,sizeof(proxy));
if(iRetVal == 0)
{
// Important: wait a bit until listening thread exits
WaitForSingleObject(m_hListeningThread,5000);
}
else
{
TCHAR szMsg[MAX_PATH];
HRESULT hr = StringCchPrintf(szMsg, sizeof(szMsg),
_T("CloseListeningThread: connect() failed with error %d"),WS2_WSAGetLastError());
Trace(szMsg);
}
}
}
}
return iRetVal;
}
---The listening thread-----
Code:
TCHAR szMsg[MAX_PATH];
int fromlen;
struct sockaddr_in from;
// listening loop snippet
while(1)
{
fromlen =sizeof(from);
m_sckLatestClient = accept(m_listen_socket,(struct sockaddr*)&from, &fromlen);
if (m_sckLatestClient != INVALID_SOCKET)
{
if(!m_bIsShuttingDown)
{
// DO whatever the server needs to do upon being connected to
}
else
{
break; // exit the listening loop to shut down
}
}
}
closesocket(m_listen_socket);
// Here release whatever other resources the listening thread was using