5.4.2接受客户端请求线程

来源:互联网 发布:威新软件科技园 编辑:程序博客网 时间:2024/06/05 19:10

  AcceptThread()实现接受客户端的连接请求。该函数是一个for循环体。当服务器处于运行状态时,bServerRunning变量为TRUE,不断地等待客户端的连接请求。当服务器处于即将退出状态时,bServerRunning变量为假,该线程退出。

for循环体中,使用sServer非阻塞套接字不断调用accept()函数。当没有客户端请求接受时,accept()函数立即返回WSAEWOULDBLOCK错误代码。在此情况下,首先调用Sleep()函数使该线程睡眠TIMEFOR_THREAD_SLEEP时间。然后执行continue语句,继续等待客户端的连接请求。

当完成接受客户端请求时,accept()函数返回新建连接的sAccept套接字。sAccept套接字继承sServer套接字的属性。该套接字也将以非阻塞方式工作于在其调用的函数上。

然后,在临界区内使用sAccept套接字和addrClient客户端地址为参数创建一个CClient类的实例。将该实例作为一个节点加入clientlist链表中。

最后调用CClient类的StartRuning()函数,为该客户端创建接收和发送数据线程。关于CClient类将在下面一节中介绍。接受客户端请求线程的程序清单如下。

#define TIMEFOR_THREAD_SLEEP                  500            //等待客户端请求线程睡眠时间

/**

 * 接受客户端请求

 */

DWORD __stdcall AcceptThread(void* pParam)

{

         SOCKET  sAccept;                                                          //接受客户端连接的套接字

         sockaddr_in addrClient;                                                  //客户端SOCKET地址

 

         for (;bServerRunning;)                                                                                           //服务器的状态

         {

                   memset(&addrClient, 0, sizeof(sockaddr_in));                                      //初始化

                   int                        lenClient = sizeof(sockaddr_in);                                             //地址长度

                   sAccept = accept(sServer, (sockaddr*)&addrClient, &lenClient);       //接受客户请求

 

                   if(INVALID_SOCKET == sAccept )

                   {

                            int nErrCode = WSAGetLastError();

                            if(nErrCode == WSAEWOULDBLOCK)      //无法立即完成一个非阻挡性套接字操作

                            {

                                     Sleep(TIMEFOR_THREAD_SLEEP);

                                     continue;                                                 //继续等待

                            }else {

                                     return 0;                                                  //线程退出

                            }

                   }

                   else                                                                            //接受客户端的请求

                   {

                            CClient *pClient = new CClient(sAccept,addrClient);         //创建客户端对象

                            EnterCriticalSection(&csClientList);                             //进入在临界区

                            clientlist.push_back(pClient);                                        //加入链表

                            LeaveCriticalSection(&csClientList);                                     //离开临界区

                           

                            pClient->StartRuning();                                 //为接受的客户端建立接收数据和发送数据线程

                   }

         }

 

         return 0;//线程退出

}

原创粉丝点击