164 lines
5.6 KiB
C
164 lines
5.6 KiB
C
|
#ifndef HGL_NETWORK_MULTI_THREAD_TCP_SERVER_INCLUDE
|
|||
|
#define HGL_NETWORK_MULTI_THREAD_TCP_SERVER_INCLUDE
|
|||
|
|
|||
|
#include<hgl/network/TCPAccept.h>
|
|||
|
#include<hgl/network/TCPServer.h>
|
|||
|
#include<hgl/network/MultiThreadAccept.h>
|
|||
|
#include<hgl/network/SocketManageThread.h>
|
|||
|
#include<hgl/Time.h>
|
|||
|
|
|||
|
namespace hgl
|
|||
|
{
|
|||
|
namespace network
|
|||
|
{
|
|||
|
/**
|
|||
|
* 多线程TCP服务器
|
|||
|
*/
|
|||
|
template<typename USER_ACCEPT,typename SOCKET_MANAGE_THREAD> class MTTCPServer
|
|||
|
{
|
|||
|
protected:
|
|||
|
|
|||
|
class Accept2SocketManageThread:public AcceptThread
|
|||
|
{
|
|||
|
SOCKET_MANAGE_THREAD *sm_thread;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
using AcceptThread::AcceptThread;
|
|||
|
|
|||
|
void SetSocketManage(SOCKET_MANAGE_THREAD *smt)
|
|||
|
{
|
|||
|
sm_thread=smt;
|
|||
|
}
|
|||
|
|
|||
|
bool OnAccept(int client_sock,IPAddress *ip_address) override
|
|||
|
{
|
|||
|
if(!sm_thread)return(false);
|
|||
|
|
|||
|
USER_ACCEPT *us;
|
|||
|
|
|||
|
us=new USER_ACCEPT(client_sock,ip_address); //这个new非常占时间,未来放到各自的线程去做
|
|||
|
|
|||
|
auto &sl=sm_thread->JoinBegin();
|
|||
|
|
|||
|
sl.Add(us);
|
|||
|
|
|||
|
sm_thread->JoinEnd();
|
|||
|
|
|||
|
return(true);
|
|||
|
}
|
|||
|
};//class Accept2SocketManageThread:public AcceptThread
|
|||
|
|
|||
|
protected:
|
|||
|
|
|||
|
IPAddress * server_ip=nullptr;
|
|||
|
TCPServer server;
|
|||
|
|
|||
|
MultiThreadAccept<Accept2SocketManageThread> accept_manage;
|
|||
|
MultiThreadManage<SOCKET_MANAGE_THREAD> sock_manage;
|
|||
|
|
|||
|
protected:
|
|||
|
|
|||
|
virtual SOCKET_MANAGE_THREAD *CreateSocketManageThread(int max_user)
|
|||
|
{
|
|||
|
SocketManage *sm=new SocketManage(max_user);
|
|||
|
SOCKET_MANAGE_THREAD *smt=new SOCKET_MANAGE_THREAD(sm);
|
|||
|
|
|||
|
return smt;
|
|||
|
}
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
/**
|
|||
|
* 服务器初始化信息结构
|
|||
|
*/
|
|||
|
struct InitInfomation
|
|||
|
{
|
|||
|
IPAddress * server_ip =nullptr; ///<服务器IP地址
|
|||
|
bool port_reuse =false; ///<端口复用
|
|||
|
bool ipv6_only =false; ///<是否使用IPv6 Only
|
|||
|
bool block =true; ///<是否使用阻塞模式
|
|||
|
uint defer_accept_time =1; ///<延迟Accept成功超时时间,单位:秒(第一次收到数据才会成功Accept,这里指从connect到第一个包的超时时间)
|
|||
|
double accept_time_out =1; ///<Accept超时时间,单位:秒
|
|||
|
|
|||
|
uint max_user =1024; ///<最大用户数量
|
|||
|
uint thread_count =4; ///<线程数量
|
|||
|
};//struct MTTCPServerInitInfomation
|
|||
|
|
|||
|
bool Init(InitInfomation &info)
|
|||
|
{
|
|||
|
if(!info.server_ip)return(false);
|
|||
|
if(info.max_user<=0)return(false);
|
|||
|
if(info.thread_count<=0)return(false);
|
|||
|
|
|||
|
if(!server.CreateServer(info.server_ip,info.max_user,info.port_reuse))
|
|||
|
return(false);
|
|||
|
|
|||
|
if(info.server_ip->GetFamily()==AF_INET6) //如果是IPv6地址
|
|||
|
server.SetIPv6Only(info.ipv6_only); //设置是否仅使用IPv6,这个有可能失败,但是不管它
|
|||
|
|
|||
|
server.SetBlock(true); //设置使用阻塞模式
|
|||
|
|
|||
|
#if HGL_OS != HGL_OS_Windows
|
|||
|
server.SetDeferAccept(info.defer_accept_time); //指定时间内收到数据才会产生accept
|
|||
|
#endif
|
|||
|
|
|||
|
server.SetTimeOut(info.accept_time_out); //设置accept超时时间
|
|||
|
|
|||
|
if(!accept_manage.Init(&server,info.thread_count))
|
|||
|
return(false);
|
|||
|
|
|||
|
for(int i=0;i<info.thread_count;i++)
|
|||
|
{
|
|||
|
Accept2SocketManageThread *at=accept_manage.GetAcceptThread(i);
|
|||
|
|
|||
|
SOCKET_MANAGE_THREAD *smt=CreateSocketManageThread(info.max_user);
|
|||
|
|
|||
|
at->SetSocketManage(smt);
|
|||
|
|
|||
|
sock_manage.Add(smt);
|
|||
|
}
|
|||
|
|
|||
|
if(!sock_manage.Start())
|
|||
|
return(false);
|
|||
|
|
|||
|
if(!accept_manage.Start())
|
|||
|
{
|
|||
|
sock_manage.Close();
|
|||
|
return(false);
|
|||
|
}
|
|||
|
|
|||
|
server_ip=info.server_ip;
|
|||
|
|
|||
|
return(true);
|
|||
|
}
|
|||
|
|
|||
|
int IsLive()
|
|||
|
{
|
|||
|
return(sock_manage.IsLive()+accept_manage.IsLive());
|
|||
|
}
|
|||
|
|
|||
|
bool Wait(const double &time_out=HGL_NETWORK_TIME_OUT)
|
|||
|
{
|
|||
|
WaitTime(time_out);
|
|||
|
|
|||
|
const int live_s=sock_manage.IsLive();
|
|||
|
const int live_a=accept_manage.IsLive();
|
|||
|
|
|||
|
if(live_s+live_s<=0)
|
|||
|
return(false);
|
|||
|
|
|||
|
#ifdef _DEBUG
|
|||
|
std::cout<<"live accept thread "<<live_a<<", sock thread: "<<live_s<<std::endl;
|
|||
|
#endif//_DEBUG
|
|||
|
|
|||
|
return(true);
|
|||
|
}
|
|||
|
};//template<typename USER_ACCEPT,typename SOCKET_MANAGE_THREAD> class MTTCPServer
|
|||
|
|
|||
|
template<typename USER_ACCEPT>
|
|||
|
using MTTCPServerStd=MTTCPServer<USER_ACCEPT,SocketManageThread<USER_ACCEPT>>;
|
|||
|
}//namespace network
|
|||
|
}//namespace hgl
|
|||
|
#endif//HGL_NETWORK_MULTI_THREAD_TCP_SERVER_INCLUDE
|