2 启动服务器
启动服务器的主要动作就是创建一个新线程,在该线程中接收来自客户端的连接。为CTCPSocket_Server类添加public权限的成员函数StartServer(),用于启动服务器。当接收了客户端连接后,如果程序需要在主窗口中显示该客户端的信息,则需要在StartServer()中调用主窗口的函数,这就要用到回调函数。在CTCPSocket_Server类中定义函数指针的成员变量,用于回调函数。当在主窗口中调用StartServer()时,指定回调函数。
2.1 定义函数指针类型
在前面我们已经提到,在CTCPSocket_Server类定义函数指针类型的成员变量。因此,在TCPSocket_Server.h中首先定义函数指针类型。
typedef void(*LPStatusProc)(char* data, int length, DWORD userdata);
以上代码定义了名为LPStatusProc
的函数指针,该函数的返回值是
void
,参数分别为
char*
、
int
和
DWROD
。
函数指针:是指向函数而非指向对象的指针。像其它指针一样,函数指针也指向某个特定的类型。函数类型由其返回类型以及形参表确定,而与函数名无关。用typedef可以为指针类型定义同义词,可以将函数指针的使用大大简化。
2.2 定义函数指针类型的成员变量
为CTCPSocket_Server类定义三个类型为LPStatusProc的成员变量,这两个成员变量分别作为接受客户端连接时的回调函数、收到客户端数据时以及客户端断开套接字时的回调函数,其访问权限为private。
LPStatusProc m_acceptclient_proc;
LPStatusProc m_receiveclientdata_proc;
LPStatusProc m_disconnectclient_proc;
2.3 StartServer()函数
2.3.1 声明
在“2.2 定义函数指针类型的成员变量”中提到,StartServer()函数中会用到三个回调函数,因此StartServer()函数有三个参数,分别表示这三个回调函数。
为CTCPSocket_Server类添加成员函数StartServer(),其访问权限为public
bool CTCPSocket_Server::StartServer(LPStatusProc proc_accept, LPStatusProc proc_recv, LPStatusProc proc_disconnect);
2.3.2 指定回调函数
在StartServer()中,将参数值赋值给“2.2 定义函数指针类型的成员变量”中声明的三个函数指针的变量。
m_acceptclient_proc = proc_accept;
m_receiveclientdata_proc = proc_recv;
m_disconnectclient_proc = proc_disconnect;
之后,在StartServer()
中就可以使用
m_acceptclient_proc
和
m_receiveclientdata_proc
来处理客户端信息和客户端数据了。在主窗口程序中,通过调用
StartServer()
为
m_acceptclient_proc
和
m_receiveclientdata_proc
指定具体的函数。
2.3.3 定义线程函数
在指定了回调函数之后,接下来通过CreateThread()函数创建新线程接收客户端的连接。CreateThread()函数要求其创建的线程函数必须是全局的或静态的,所以在创建线程之前需要定义线程函数。
CTCPSocket_Server类中添加static的成员函数,该函数作为CreateThread()函数的线程函数。
(1)声明
该线程函数声明为
static DWORD ThreadFunc_StartServer(LPVOID lpParameter);
该格式为CreateThread()
函数要求的线程函数格式。
(2)获取类对象指针
在TCPSocket_Server.cpp文件中对该函数进行定义。因为类的静态函数只能访问类静态变量或全局变量,为了在静态函数中访问类对象的成员,可以将静态函数的参数设置为类对象的指针,在静态函数中获取该对象的指针。
CTCPSocket_Server* pServer = (CTCPSocket_Server*)lpParameter;
之后,在静态函数ThreadFunc_StartServer
中,就可以通过类对象的指针
pServer
来访问类对象的成员了。