Listening socket and thread problem
To outline the problem: I have a socket server listening in a seperate thread to the main program. The socket accepts new connections and deals with them, then listens again. It is in a while loop.
When I click on the button to shut down the socket server, I can not figure out a way to close the thread with the listening socket in it, because it is stuck on the line where it listens. Only after I open a connection and it runs though the code again and realises that run is set to false does the thread close.
This is obviously a problem as when I click shutdown server I want the server to shut down now, not after the next connection!
rough outline:
Code:
(inside the thread)
while 1
{
socket->listen
(deal with connection)
if run is false return 0
}
I am using winsock and windows CreateThread if that is important.
So, does anyone know a way to either run the listening socket differently, or shut down the thread somehow? I wanted to avoid TerminateThread as it doesn't clear everything.
Thanks a lot in advance for all your help.
esaptonor
The way I used to terminate the thread listening on the socket
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