📄 sgiapi.cpp
字号:
m_sSrcNum = sSrcNum; //源节点编码
m_nSubmitConn = nConnCount; //sp连接网关的连接数
m_nMaxSmgConn = nMaxSmgConn; //网关连接到sp的最大数
m_nMinWorkThreadsCount = nMinWorkThreadsCount; // 线程池初始线程数
m_nMaxWorkThreadsCount = nMaxWorkThreadsCount; // 允许的线程池最大线程数
if (m_nSubmitConn > MAX_PATH)
m_nSubmitConn = MAX_PATH;
if (m_nMinWorkThreadsCount > m_nMaxWorkThreadsCount)
m_nMaxWorkThreadsCount = m_nMinWorkThreadsCount;
//设为-1则不启动本地监听,则不接收网关的连接和消息
//不为-1则监听,启动接受部分
if (nLocalPort != -1)
{
if (!LocalListen())
return -1;
}
//设为-1,则不连接网关,即不发送
//否则连接网关,预备执行发送
if (nPeerPort != -1)
{
if (!CreateConn())
return -1;
}
//启动线程池
pool.Start(m_nMinWorkThreadsCount, m_nMaxWorkThreadsCount);
return 0;
}
/*
断开连接,停止线程池,释放资源
如果Start没有启动成功,是否强制释放
*/
void CSgip::Release(BOOL forceRelease)
{
pool.Stop(forceRelease == TRUE); //停止线程池的处理
ReleaseConn(); //释放连接网关socket
m_fStop = true;
closesocket(serverSocket); //关闭服务监听端口
}
/*
提交MT消息
nDatetime(submit包的时间戳,序列号中的第二个字段),
与nSeq结合能够做到唯一标识一条submit消息(即使系统重新启动,nSeq重新归零).
ss, Submit消息包
&nSeq, 该消息包的序列号中的序列号
&nDateTime 该消息包的序列号中的时间戳
nSeq,nDateTime都是输出参数。
nDateTime 格式: mmddhhmmss 10位数
*/
void CSgip::Submit(sgipg_submit ss, unsigned &nSeq, unsigned &nDateTime)
{
nDateTime = sgip_get_datetime();
nSeq = GetSubmitSeqId(); //获取提交的序列号
SubmitFunc(ss, nSeq, nDateTime);
}
/*
支持群发的设置目的号码的函数.
sUserNumber可以是单个的手机号码,或者以逗号,中划线隔开的多个号码.
可以是以下几种类型之一,例如:"8613312345678",或"8613312345678,86133123456789",
或"8613312345670-8613312345679",或"8613312345670,8613312345675-8613312345689",或"8613012345678,8613012345679-8613012345688,8613312312312"。
sgipg_submit* ss, 要群发的消息包
const char* sUserNumber 要增加的群发手机号
*/
int CSgip::AddUserNumber(sgipg_submit* ss,const char* sUserNumber)
{
return 0;
}
/*
下一条要发submit消息的序列号
其实读取,该运行估计需要在lock下最好,
其次为int,2 32 次方=4294967296 则复位,
而submit可以保留2*64次方的计数
采用long强行转化也行.
*/
unsigned int CSgip::GetSubmitSeqId()
{
static SeqId = 1;
SeqId++;
if (SeqId == 0) SeqId = 1;
return SeqId;
}
/*
发送消息
获取连接网关的socket,然后,调用jobsgip处理
*/
int CSgip::SubmitFunc(sgipg_submit ss, unsigned int nSeq, unsigned int nDateTime)
{
m_pJob = new CJobSgip(ss, this, nSeq, nDateTime);
m_worker.ProcessJob(m_pJob);
return 0;
}
/*
当start,需要启动本地端口进行监听.
如果不能监听就返回
*/
bool CSgip::LocalListen()
{
return (listen(serverSocket, m_nMaxSmgConn) != SOCKET_ERROR);
}
bool CSgip::IsValidIPAddr(LPCTSTR sIPAddr)
{
return true;
}
/*
创建log 文件
*/
bool CSgip::CreateLogFile()
{
return 0;
}
/*
获取socket用于发送submit
*/
sgip_conn* CSgip::GetSubmitConn(int &nConnIndex)
{
ASSERT(m_nSubmitConn > 0);
m_nConnIndex = 0;
nConnIndex = 0;
sgip_conn * ret_sgipConn = &SubmitConn[0]; //找不到返回第一个socket
for(int i = 0; i < m_nSubmitConn; i++)
{
if (SubmitConn[i].hSocket != NULL)
{
if (!SubmitConn[i].fBusy)
{
m_nConnIndex = i; //保存该索引号
nConnIndex = i;
ret_sgipConn = &SubmitConn[i];
break;
}
}
}
return ret_sgipConn;
}
/*
改变连接网关的socket状态
*/
void CSgip::ChangeStatus(int nConnIndex, bool fBusy)
{
if (nConnIndex > MAX_PATH )
return;
//改变连接网关的状态
m_arrayCs.Lock();
SubmitConn[nConnIndex].fBusy = fBusy;
m_arrayCs.Unlock();
}
/*
登陆smg时,先要binded,成功返回验证成功,
*/
int CSgip::LoginSmg(sgip_conn *pConn)
{
sgipg_connect sc;
if (!pConn->fBinded)
{
sgip_login_value_set(&sc, 1, (LPCTSTR)m_sUserName, (LPCTSTR)m_sPwd);
int nSeq = GetSubmitSeqId();
int iRet = sgip_login(pConn, &sc, (LPCSTR)m_sSrcNum, nSeq); //包括bind回来处理
if(iRet == 0)
{
pConn->fBinded = true;
return 0;
}
else
{
pConn->nCount++; //重连次数
return -1;
}
}
return 0;
}
/*
sp连向网关退出的unbind 行为
*/
void CSgip::LogoutSmg(sgip_conn *pConn)
{
int nSeq = 0,
iRet;
if (pConn->fBinded)
{
iRet = sgip_logout(pConn, nSeq);
if(iRet == 0)
{
pConn->fBinded = false;
}
}
}
/****************************************************
sp到网关的连接,采用的是长连接方式,即连接后放置在数组中
创建socket 到该端口的连接,注意没有bind
*/
bool CSgip::CreateConn()
{
if (m_sUserName.IsEmpty() || m_sPeerAddr.IsEmpty())
return false;
for(int i = 0; i < m_nSubmitConn; i++ )
{
if (sgip_connect_to_ismg((LPCTSTR)m_sPeerAddr, m_nPeerPort, &SubmitConn[i]) != SGIP_SUCCESS)
return false;
if (LoginSmg(&SubmitConn[i]) == 0)//bind 包发送
{
SubmitConn[i].fBinded = true;
}
}
return true;
}
/*
释放所有的到网关连接
把所有的socket都关闭.
如果没有Unbind也需要bind?
*/
bool CSgip::ReleaseConn()
{
//断开连接
for(int i = 0; i < m_nSubmitConn; i++ )
{
LogoutSmg(&SubmitConn[i]);
sgip_disconnect_from_ismg(&SubmitConn[i]);
}
return true;
}
/*
smg连接sp加入列表
*/
void CSgip::AddSmgConn(unsigned socketHandle, unsigned port)
{
ASSERT(socketHandle != NULL);
ConnInfo smgConn(socketHandle, port,GetDateTime());
connList.push_back(smgConn);
}
/*
移出该网关连接socket
*/
void CSgip::RemoveSmgConn(unsigned socketHandle)
{
list<ConnInfo>::iterator pIt;
for (pIt = connList.begin(); pIt != connList.end(); pIt++)
{
if (pIt->socketHandle == socketHandle)
{
connList.erase(pIt);
break;
}
}
}
/********************************************************
获得日期时间函数 格式"04d-02d-02d 02d:02d:02d",
即YYYY-MM-DD hh:mm:ss:mss,主要用于记录日志的记录的时间戳
*/
CString CSgip::GetDateTime()
{
CString sTime;
//CTime now = CTime::GetCurrentTime();
//sTime = now.Format("%Y-%m-%d %H:%M:%S"));
SYSTEMTIME systime;
GetSystemTime(&systime);
sTime.Format("%04d-%02d-%02d %02d:%02d:%02d:%03d", systime.wYear, systime.wMonth,
systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds);
return sTime;
}
/*
线程处理体
*/
DWORD WINAPI CSgip::SgipServFunc(LPVOID pParam)
{
CSgip* mySgip = (CSgip*)pParam;
try{
mySgip->SgipServProc();
}
catch(...)
{
}
return 0;
}
/*
处于监听accept状态.当有网关连接时,启动上行工作处理
*/
DWORD CSgip::SgipServProc()
{
SOCKET smgSocket;
int iAddrSize;
struct sockaddr_in addr;
iAddrSize = sizeof(addr);
while(1)
{
if (m_fStop)
break;
smgSocket = accept(serverSocket, (struct sockaddr *)&addr, &iAddrSize);
//接入端口错误,退出
if(smgSocket == SOCKET_ERROR)
{
break;
}
//增加socket到clist列表中
AddSmgConn(smgSocket, addr.sin_port);
//启动job工作接受信息包
m_pJob = new CJobSgip(smgSocket, this, addr.sin_port);
m_worker.ProcessJob(m_pJob);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -