MFC基于select模型的套接字类之服务器(8)

来源:互联网 发布:中海达数据导出 编辑:程序博客网 时间:2024/06/06 03:39

4 停止服务器

CTCPSocket_Server类添加访问权限为public的成员函数StopServer()。在该函数中主要完成的工作是关闭“2.3 StartServer()函数”中提到了用于接受客户端连接的线程和用于接收客户端数据的线程。

4.1 结束接受客户端连接的线程

2.3 StartServer()函数”中提到,该线程由CTCPSocket_Server类的成员变量m_acceptthread_alive来控制。当该变量的值是false时,线程函数中的while()循环将退出,结束线程。

StopServer()函数中,首先将m_acceptthread_alive设置为false

m_acceptthread_alive = false;
接下来使用WaitForSingleObject()函数等待该线程结束。

WaitForSingleObject(m_acceptthread_handle, 1000);
WaitForSingleObject()函数的第一个参数指定了等待线程的句柄,第二个参数表示等待的时间,单位为毫秒。在等待了1秒钟之后,调用GetExitCodeThread()函数判断指定的线程是否结束,如果未结束,则调用TerminateThread()函数强行退出。

DWORD exitcode_thread = 0;if (!GetExitCodeThread(m_acceptthread_handle, &exitcode_thread) || exitcode_thread == STILL_ACTIVE){TerminateThread(m_acceptthread_handle, exitcode_thread);}CloseHandle(m_acceptthread_handle);m_acceptthread_handle = NULL;
GetExitCodeThread()函数的第一个参数表示指定线程的句柄;第二个参数是线程的退出码。如果指定的线程已经结束,则该函数的返回值是非零,如果线程未结束,则退出码exitcode_thread的值是STILL_ACTIVE,如果函数执行失败,则返回值为0。在将线程退出之后,将调用CloseHandle()函数关闭线程句柄,并且将线程句柄清空。

4.2 关闭监听连接的套接字

2.3.5创建新线程接收数据”中提到,可以“优雅”关闭套接字,也可以“强行”关闭套接字。使用“优雅”的方式关闭套接字时,在调用closesocket()函数之前,需要调用shutdown()函数来禁止套接字的发送和接收动作。该函数的格式为

int shutdown(SOCKET s, int how);
其中,参数s指定了要指定动作的套接字;how表示禁止套接字的什么动作,该参数是SD_RECEIVE时,表示禁止套接字接收数据,SD_SEND表示禁止套接字发送数据,SD_BOTH表示进制套接字收发数据。

shutdown(m_socket_listen, SD_BOTH);closesocket(m_socket_listen);m_socket_listen = NULL;

4.3结束接收客户端数据的线程

用于接收客户端数据的线程句柄都保存在2.3.6创建接收客户端数据的线程”中介绍的CTCPSocket_Server类的m_recvdata_threadhandle_array中。

for (int i = 0; i < MAX_CONNECTION; ++i){if (m_clientconnectflag_array[i]){m_clientconnectflag_array[i] = false;WaitForSingleObject(m_recvdata_threadhandle_array[i], 500);if (!GetExitCodeThread(m_recvdata_threadhandle_array[i], &exitcode) || exitcode==STILL_ACTIVE){TerminateThread(m_recvdata_threadhandle_array[i], exitcode);}CloseHandle(m_recvdata_threadhandle_array[i]);m_recvdata_threadhandle_array[i] = NULL;         .............          }   }
以上代码的作用是结束m_recvdata_threadhandle_array中保存的句柄对应的线程。结束线程的方法与“4.1结束接受客户端连接的线程”中提到的方法相同。

4.4 优雅关闭与客户端通信的套接字

在结束了接收客户端数据的线程之后,在4.3结束接收客户端数据的线程”中代码的for循环中,继续优雅关闭与客户端通信的套接字。优雅关闭套接字的方法与“4.2关闭监听连接的套接字”中提到的方法相同。

shutdown(m_clientsocket_array[i], SD_BOTH);closesocket(m_clientsocket_array[i]);m_clientsocket_array[i] = NULL;