#define WIN32 1
#include <stdio.h>
#include <pinet.h>
#include <ptime.h>
#include "packet.h"
#include "logfile1.h"
#include "config.h"
#ifdef WIN32
#pragma comment(lib, "ptypes.lib")
#pragma comment(lib, "ws2_32.lib")
#endif
USING_PTYPES
const int testport = 8088;
const int maxtoken = 4096;
const int maxthreads = 10000;
const int MSG_MYJOB = MSG_USER + 1;
bool g_bStop = false;
struct CLIENTINFO
{
ipstream *pClient;
CPacket *pPacket;
};
class myjobthread: public thread
{
protected:
int id;
jobqueue* jq;
virtual void execute();
void stopclear()
{
//停止时初始化一些变量
running = 0;
#ifdef WIN32
CloseHandle(handle);
#else
pthread_join(handle, nil);
#endif
}
public:
myjobthread(int iid, jobqueue* ijq)
: thread(false), id(iid), jq(ijq) {}
~myjobthread() { waitfor(); }
};
class myjob: public message
{
public:
CLIENTINFO* m_pClientInfo;
myjob(CLIENTINFO* pClientInfo)
: message(MSG_MYJOB), m_pClientInfo(pClientInfo) {}
~myjob()
{
delete m_pClientInfo->pClient;
delete m_pClientInfo->pPacket;
delete m_pClientInfo;
}
};
void myjobthread::execute()
{
bool quit = false;
pout.putf("%t 进入线程ID: %d \n",now(),id);
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "进入线程ID:%d", id);
while (!quit )
{
// get the next message from the queue
message* msg = jq->getmessage();
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "获取到消息队列 线程ID:%d", id);
try
{
switch (msg->id)
{
case MSG_MYJOB:
{
BYTE szBuffer[MAXTOKEN];
memset(szBuffer, 0x00, sizeof(szBuffer));
CPacket* pPacket = ((myjob*)msg)->m_pClientInfo->pPacket;
ipstream* pClient = ((myjob*)msg)->m_pClientInfo->pClient;
//循环发送接收
while(!g_bStop)
{
int nLength = pPacket->Encode((BYTE*)szBuffer, MAXTOKEN);
pout.putf("%t Sending a request to the server... threadID:%d \n",now(), id);
//为了测试大连接,需要每个线程休眠一小段时间,等待其他线程进来。
//Sleep(10000);
//client.putline((char *)szBuffer);
pClient->write(szBuffer, nLength);
pClient->flush();
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "发送数据成功,Socket:%d 长度:%d threadID:%d ",pClient->get_handle(), nLength, id);
// receive the response
//超时或者出错退出
if (!pClient->waitfor(30000))
{
pout.putf("%t 网络接收超时或出错, Socket:%d \n",now(),pClient->get_handle());
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_WARN, "网络接收超时或出错, Socket:%d threadID:%d", pClient->get_handle(), id);
break;
}
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "waitfor响应 ");
memset(szBuffer, 0x00, sizeof(szBuffer));
int nLen1=0,nLen2 = 0,nRemainLen=0;
nLen1 = pClient->read(szBuffer,sizeof(UINT32)*3);
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "接收数据成功1,Socket:%d 长度:%d threadID:%d ",pClient->get_handle(), nLen1, id);
if (nLen1 <= 0)
{
break;
}
nRemainLen = *(UINT32*)(szBuffer + sizeof(UINT32)*2) + sizeof(UINT32);
nLen2 = pClient->read(szBuffer + nLen1, nRemainLen);
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "接收数据成功2,Socket:%d 长度:%d threadID:%d ",pClient->get_handle(), nLen2, id);
if (nLen2 <= 0)
{
break;
}
UINT32 nCmdID = CPacket::GetCmdIDFromData(szBuffer);
pout.putf("%t Received: CMDID:%x\n", now(), nCmdID);
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "接收数据成功,Socket:%d 长度:%d threadID:%d ",pClient->get_handle(), nLength, id);
//Sleep(1000000);
}
pClient->close();
}
break;
case MSG_QUIT:
// MSG_QUIT is not used in our example
quit = true;
break;
}
}
catch(exception*)
{
// the message object must be freed!
delete msg;
throw;
}
delete msg;
}
pout.putf("%t 退出线程ID: %d \n",now(),id);
CLogFile::Instance()->LOG_WriteLine(LOG_INFO_HIT, "退出线程ID:%d", id);
//清除线程句柄
stopclear();
}
int main()
{
CLogFile::Instance()->LOG_Start(".\\clipoollog\\");
//获取配置文件
CConfig cfConfig;
char szServerIP[32];
memset(szServerIP, 0x00, sizeof(szServerIP));
int nPort = 0;
int nThreadNum = 0;
cfConfig.ReadConfigString("server", "ip", szServerIP, "127.0.0.1", 32, ".\\clipool.ini");
nPort = cfConfig.ReadConfigInt("server", "port", testport, ".\\clipool.ini");
nThreadNum = cfConfig.ReadConfigInt("client", "threadnum", maxthreads, ".\\clipool.ini");
//创建线程池
jobqueue jobQueue;
tobjlist<myjobthread> threads(true);
myjobthread* pArrJobThread[maxthreads];
// create the thread pool
for(int i = 0; i < nThreadNum; i++)
{
pArrJobThread[i] = new myjobthread(i + 1, &jobQueue);
pArrJobThread[i]->start();
threads.add(pArrJobThread[i]);
}
Sleep(10);
// create a client socket and send a greeting to the server
// assuming that the server is on the same host (127.0.0.1)
char chNum =0x00;
while(1)
{
pout.putf("=================================================================\n");
pout.putf("= 输入1 发送开锁消息 输入2 发送报警消息 =\n");
pout.putf("= 输入3 发送文件升级 输入4 发送文件升级成功消息 =\n");
pout.putf("= 输入5 发送广告升级 输入6 发送广告升级成功消息 =\n");
pout.putf("= 输入7 设备文件抓拍 输入8 发送抓拍上传成功消息 =\n");
pout.putf("= 输入a 发送时间校准 输入b 发送门禁开门过长消息 =\n");
pout.putf("= 输入s 停止操作 输入q 或其他字母结束 =\n");
pout.putf("=================================================================\n");
chNum = getchar();
getchar();
CPacket *pPacket;
g_bStop = false;
//循环启动
for(int nNum = 0; nNum < nThreadNum; nNum++)
{
if ('1' == chNum)
{
pPacket = new CPacket_OpenUnitDoor;
pPacket->SetTest(nNum);
}
else if ('2' == chNum)
{
pPacket = new CPacket_Alarm;
pPacket->SetTest(nNum);
}
else if ('3' == chNum)
{
pPacket = new CPacket_UpdateFile;
pPacket->SetTest(nNum);
}
else if ('4' == chNum)
{
pPacket = new CPacket_UpdateFile;
pPacket->SetTest2(nNum);
}
else if ('5' == chNum)
{
pPacket = new CPacket_UpdateAdvertisement;
pPacket->SetTest(nNum);
}
else if ('6' == chNum)
{
pPacket = new CPacket_UpdateAdvertisement;
pPacket->SetTest2(nNum);
}
else if ('7' == chNum)
{
pPacket = new CPacket_UploadDevicePicture;
pPacket->SetTest(nNum);
}
else if ('8' == chNum)
{
pPacket = new CPacket_UploadDevicePicture;
pPacket->SetTest2(nNum);
}
else if ('a' == chNum)
{
pPacket = new CPacket_CalibrateTime;
pPacket->SetTest();
}
else if ('b' == chNum)
{
pPacket = new CPacket_LongOpenDoor;
pPacket->SetTest(nNum);
}
else if ('s' == chNum)
{
g_bStop = true;
break;
}
else if ('q' == chNum)
{
//退出
return 0;
}
else
{
return 0;
}
CLIENTINFO *pClientInfo = new CLIENTINFO;
pClientInfo->pPacket = pPacket;
pClientInfo->pClient = new ipstream(szServerIP, nPort);
try
{
//客户端进行连接
pClientInfo->pClient->open();
pout.putf("======================================================\n");
pout.putf("%t: 第%d 客户端连接成功 Socket: %d \n", now(), nNum, pClientInfo->pClient->get_handle());
jobQueue.post(new myjob(pClientInfo));
}
catch(estream* e)
{
perr.putf("第%d Error: %s\n", nNum, pconst(e->get_message()));
delete e;
}
//delete pPacket;
} //end first for 跳出for循环
//跳出for循环再处理线程池.
if ('s' == chNum)
{
//停止清除原来的发送数据
//停止运行的线程类。
for (int i = 0; i < nThreadNum; i++)
{
//发送推出信号让线程池中运行的线程停止
jobQueue.post(MSG_QUIT);
threads.pop();
}
//启动线程池中的原线程
//启动线程池
for(int i = 0; i < nThreadNum; i++)
{
if (NULL == pArrJobThread[i])
{
pArrJobThread[i] = new myjobthread(i, &jobQueue);
}
pArrJobThread[i]->start();
threads.add(pArrJobThread[i]);
}
}
} //endwhile
return 0;
}