消息处理线程

55 篇文章 0 订阅
37 篇文章 0 订阅
消息处理线程




//函数名称:IOThreadProc
//函数功能:消息处理的线程
//处理对象:核心函数
//研究人员:长寿梦 
DWORD WINAPI CP2PServer::IOThreadProc(LPVOID  lpParam)
{
CP2PServer *pThis=(CP2PServer *)lpParam;    
char buff[MAX_PACKET_SIZE];
CP2PMessage *pMsg=(CP2PMessage *)buff;
sockaddr_in remoteAddr;
//
WSABUF wsaBuf;
wsaBuf.buf=buff;
wsaBuf.len=MAX_PACKET_SIZE;
//
DWORD dwRecv;
DWORD dwFlags=0;
int nAddrLen=sizeof(remoteAddr);


_RecordsetPtr m_record;     //记录集, 记录ADO查询的数据
_bstr_t vSQL;    //SQL语句
CString strNo,strName,strPhone,strText,strLog,strTime;
CString strPassword,strIp,strPort,strOnline;
COleDateTime time;


while(TRUE)
{    //    接收信息到wsaBuf
int nRet=::WSARecvFrom(pThis->g_s,&wsaBuf,1,&dwRecv,&dwFlags,(sockaddr *)&remoteAddr,&nAddrLen,&pThis->g_ol,NULL);


if(nRet==SOCKET_ERROR) 
{
int nError=::WSAGetLastError();
if(nError==WSA_IO_PENDING)
{   
//    TRACE0("没接到消息,正在等待。。。重叠接收信息\n");
::WSAGetOverlappedResult(pThis->g_s,&pThis->g_ol,&dwRecv,TRUE,&dwFlags);    
}
//else if()
}
//查看是否要退出
if(pThis->g_bThreadExit) 
break;
if(dwRecv<sizeof(CP2PMessage))
continue;
//消息循环:总共处理15个消息
switch(pMsg->nMessageType)
{   
//[1/15]用户登陆消息//
case USERLOGIN: 
{
strNo=pMsg->peer.ImNo;
strPassword=(char*)(pMsg+1);
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strNo+" 请求登陆";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);


vSQL="select * from imuser where ImNo='"+strNo+"' and Impassword='"+strPassword+"' and ImOnline=0";
m_record=pThis->ado.GetRecordSet(vSQL);
//如果登录成功,则返回自己信息,记录登录地址,接收离线消息,接收离线好友请求,设置为在线状态,广播这状态变化
if(!m_record->adoEOF)
{  
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strNo+" 登陆成功";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);


strName=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImName");
strPhone=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPhone");


strName.TrimRight(" ");
strPhone.TrimRight(" ");


//登陆成功,并返回用户自己的信息
pMsg->nMessageType=USERLOGACK;
strcpy((char*)pMsg->peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)pMsg->peer.ImName,(LPCSTR)(LPCTSTR)strName);
strcpy((char*)pMsg->peer.ImPhone,(LPCSTR)(LPCTSTR)strPhone);
::sendto(pThis->g_s,(char *)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));
//将IP,状态写入数据库   inet_addr,inet_ntoa,
strIp=::inet_ntoa(remoteAddr.sin_addr);                 //将IP转成字符串
strPort.Format("%d",ntohs(remoteAddr.sin_port));        //将端口转成字符串,先要转化成本地字节序
vSQL="update imuser set ImOnline='1',ImIp='"+strIp+"',ImPort='"+strPort+"' where ImNo='"+strNo+"'";
pThis->ado.ExecuteSQL(vSQL);
//设置服务器该用户在线状态
strText=strName+"("+strNo+")";
::PostMessage(g_pPage1->m_hWnd,WM_USERSTATIC_UPDATE,(WPARAM)(LPCTSTR)strText,(LPARAM)(LPCTSTR)"Login");


//发送离线的消息:对表[OfflineMessage]的操作
vSQL="select * from OfflineMessage where ImNo='"+strNo+"'";  
m_record=pThis->ado.GetRecordSet(vSQL);
::Sleep(500);        /
char *pBuf = NULL;
char sendBuf[MAX_PACKET_SIZE];
while(!m_record->adoEOF)
{
long lDataSize = m_record->GetFields()->GetItem("ImMsg")->ActualSize;///得到数据的长度
if(lDataSize > 0)
{
_variant_t varBLOB;
varBLOB = m_record->GetFields()->GetItem("ImMsg")->Value;
if(varBLOB.vt == (VT_ARRAY | VT_UI1)) ///判断数据类型是否正确
{
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);///得到指向数据的指针
/*****在这里我们可以对pBuf中的数据进行处理*****/            
memset(sendBuf,0,MAX_PACKET_SIZE);
memcpy(sendBuf,pBuf,lDataSize);
SafeArrayUnaccessData (varBLOB.parray);
CP2PMessage *pM=(CP2PMessage *)sendBuf;
pM->nMessageType=P2PMESSAGE;
CString sss=(char *)(pM+1)+sizeof(MessageInfo);
//AfxMessageBox(sss);
::sendto(pThis->g_s,(char *)sendBuf,lDataSize,0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));


}
}
m_record->MoveNext();
}
//删除该用户的离线好友请求
vSQL="delete from OfflineMessage where ImNo='"+strNo+"'";
pThis->ado.ExecuteSQL(vSQL);


//发送离线好友请求的消息:对表[OffAddfriend]的操作
vSQL="select * from OffAddfriend where ImNo='"+strNo+"'";  
m_record=pThis->ado.GetRecordSet(vSQL);
::Sleep(500);        /
//char *pBuf = NULL;
//char sendBuf[sizeof(CP2PMessage)+sizeof(NewFriendMessage)];
while(!m_record->adoEOF)
{
long lDataSize = m_record->GetFields()->GetItem("ImInfo")->ActualSize;///得到数据的长度
if(lDataSize > 0)
{
_variant_t varBLOB;
varBLOB = m_record->GetFields()->GetItem("ImInfo")->Value;
if(varBLOB.vt == (VT_ARRAY | VT_UI1))                                 ///判断数据类型是否正确
{
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);              ///得到指向数据的指针
/*****在这里我们可以对pBuf中的数据进行处理*****/            
memset(sendBuf,0,MAX_PACKET_SIZE);
memcpy(sendBuf,pBuf,lDataSize);
SafeArrayUnaccessData (varBLOB.parray);        
::sendto(pThis->g_s,(char *)sendBuf,lDataSize,0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));


}
}
m_record->MoveNext();
}
//删除该用户的离线好友请求
vSQL="delete from OffAddfriend where ImNo='"+strNo+"'";
pThis->ado.ExecuteSQL(vSQL);


//给所有用户发送消息,该用户状态发生了变化
vSQL="select ImIp,ImPort,ImOnline from imuser where ImNo!='"+strNo+"'and ImOnline=1";  //只要IP地址和端口号
m_record=pThis->ado.GetRecordSet(vSQL);
while(!m_record->adoEOF)
{
//保存状态改变的用户信息(登陆的用户)
CP2PMessage peerMsg={0};
peerMsg.nMessageType=CHANGESTATE;    //改变状态消息
strcpy((char*)peerMsg.peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)peerMsg.peer.ImName,(LPCSTR)(LPCTSTR)strName);
peerMsg.peer.ImOnline=1;


//要发送对象的地址                        
strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");
strIp.TrimRight(" ");
strPort.TrimRight(" ");
strOnline.TrimRight(" ");


remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);
remoteAddr.sin_port=htons(atoi(strPort));
if(strOnline=="1" && strPort!="0")
::sendto(pThis->g_s,(char *)&peerMsg,sizeof(peerMsg),0,(sockaddr *)&remoteAddr,sizeof(remoteAddr));
m_record->MoveNext();
}



//如果登录失败
else
{
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strNo+" 登陆失败";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
}
}
break;


//[2/15]注销///
case USERLOGOUT:
{
strNo=pMsg->peer.ImNo;
strName=pMsg->peer.ImName;
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strNo+" 退出";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);


vSQL="update imuser set ImOnline='0',ImPort='0' where ImNo='"+strNo+"'";
pThis->ado.ExecuteSQL(vSQL);
//离线状态
strText=strName+"("+strNo+")";
::PostMessage(g_pPage1->m_hWnd,WM_USERSTATIC_UPDATE,(WPARAM)(LPCTSTR)strText,(LPARAM)(LPCTSTR)"Logout");


//给所有用户发送消息,该用户状态发生了变化
vSQL="select ImIp,ImPort,ImOnline from imuser where ImNo!='"+strNo+"'and ImOnline=1";  //只要IP地址和端口号
m_record=pThis->ado.GetRecordSet(vSQL);
while(!m_record->adoEOF)
{
//保存状态改变的用户信息(登陆的用户)
CP2PMessage peerMsg={0};
peerMsg.nMessageType=CHANGESTATE;    //改变状态消息
strcpy((char*)peerMsg.peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)peerMsg.peer.ImName,(LPCSTR)(LPCTSTR)strName);
peerMsg.peer.ImOnline=0;
//要发送对象的地址


strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");
strIp.TrimRight(" ");
strPort.TrimRight(" ");
strOnline.TrimRight(" ");




remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);
remoteAddr.sin_port=htons(atoi(strPort));
if(strOnline=="1" && strPort!="0")
::sendto(pThis->g_s,(char *)&peerMsg,sizeof(peerMsg),0,(sockaddr *)&remoteAddr,sizeof(remoteAddr));
m_record->MoveNext();
}




}
break;




//[3/15]获取通讯录列表/
case GETUSERLIST:   
{
int Online=0;
strNo=pMsg->peer.ImNo;
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strNo+" 获取通讯录列表";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
//
vSQL="select ImNo,ImName,ImOnline from imuser where ImNo!='"+strNo+"'";
m_record=pThis->ado.GetRecordSet(vSQL);
while(!m_record->adoEOF)
{
CP2PMessage peerMsg={0};
strNo=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImNo");
strName=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImName");
Online=atoi((LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline"));
//去掉空格
strNo.TrimRight(" ");
strName.TrimRight(" ");
strcpy((char*)peerMsg.peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)peerMsg.peer.ImName,(LPCSTR)(LPCTSTR)strName);
peerMsg.peer.ImOnline=Online;
peerMsg.nMessageType=GETUSERLISTACK;
::sendto(pThis->g_s,(char *)&peerMsg,sizeof(peerMsg),0,(sockaddr *)&remoteAddr,sizeof(remoteAddr));
m_record->MoveNext();
}


}
break;


//[4/15]获取好友列表/
case GETFRIENDLIST:
{
int Online=0;
strNo=pMsg->peer.ImNo;
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strNo+" 获取好友列表";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
//
vSQL="select ImNo,ImName,ImOnline from imuser,friend where friend.imno1='"+strNo+"' and friend.imno2=imuser.imno";
m_record=pThis->ado.GetRecordSet(vSQL);
while(!m_record->adoEOF)
{
CP2PMessage peerMsg={0};
strNo=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImNo");
strName=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImName");
Online=atoi((LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline"));
//去掉空格
strNo.TrimRight(" ");
strName.TrimRight(" ");
strcpy((char*)peerMsg.peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)peerMsg.peer.ImName,(LPCSTR)(LPCTSTR)strName);
peerMsg.peer.ImOnline=Online;
peerMsg.nMessageType=GETFRIENDLISTACK;
::sendto(pThis->g_s,(char *)&peerMsg,sizeof(peerMsg),0,(sockaddr *)&remoteAddr,sizeof(remoteAddr));
m_record->MoveNext();
}
}
break;


//[5/15]发给服务器的语音
case GETVOIP:
strNo=(char*)(pMsg+1);
//是发给服务器的语音,则返回信息,否则转发(P2PCONNECT 的处理相同)
if(strNo=="10000")
{
//有语音请求,需建立监听
::SendMessage(g_pDlg->m_hWnd,WM_NEWVOIP,NULL,NULL);
//保存发送方的端口,如果g_nVOIPPort不为0表示已经连接,还没断开
CP2PMessage ackMsg;
ackMsg.nMessageType=GETVOIPACK;
memcpy(&ackMsg.peer,&pThis->m_LocalPeer,sizeof(PEER_INFO));    
sockaddr_in peerAddr ={0};
peerAddr.sin_family=AF_INET;


if(g_nVOIPPort==0 && !g_pDlg->m_bBtnConnectDown)
{   
g_nVOIPPort=pMsg->peer.p2pAddr.nPort;
ackMsg.peer.p2pAddr.nPort=g_nLocalPort;


}
else
{
ackMsg.peer.p2pAddr.nPort=0;   //返回0表示对方正在通话中


}


for(int i=0;i<pMsg->peer.AddrNum;i++)
{  
peerAddr.sin_addr.S_un.S_addr=pMsg->peer.addr[i].dwIp;
peerAddr.sin_port=htons(pMsg->peer.addr[i].nPort);
::sendto(pThis->g_s,(char *)&ackMsg,sizeof(ackMsg),0,(sockaddr *)&peerAddr,sizeof(peerAddr));
//CString str;
//str=::inet_ntoa(peerAddr.sin_addr);
//AfxMessageBox(str);
}
break;
}


//[6/15]连接:消息转发的实现 *关键技术*/
case P2PCONNECT:    
{    
strNo=(char*)(pMsg+1);
CString strFrom=pMsg->peer.ImNo;
if(pMsg->nMessageType==P2PCONNECT)
{
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strFrom+"--->"+strNo+" 消息请求";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);


}
else
{
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strFrom+"--->"+strNo+" 语音请求";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
}


//如果A发给server,则服务器直接应答
if(strNo=="10000")
{
CP2PMessage ackMsg;
ackMsg.nMessageType=P2PCONNECTACK;
memcpy(&ackMsg.peer,&pThis->m_LocalPeer,sizeof(PEER_INFO));
::sendto(pThis->g_s,(char *)&ackMsg,sizeof(ackMsg),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));  //发送确认连接


}
//如果A发给B,则sever从数据库中搜索B地址,按此地址转发给B
else
{
vSQL="select * from imuser where ImNo='"+strNo+"' ";
m_record=pThis->ado.GetRecordSet(vSQL);
if(!m_record->adoEOF)
{  
strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");
strIp.TrimRight(" ");
strPort.TrimRight(" ");    
strOnline.TrimRight(" ");
if(strOnline=="1" && strPort!="0")
{
remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);
remoteAddr.sin_port=htons(atoi(strPort));
::sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));
}
}
else    //语音请求的账号不存在
{
if(pMsg->nMessageType==GETVOIP)
{
pMsg->nMessageType=GETVOIPACK;
pMsg->peer.p2pAddr.nPort=10000;  //端口==10000表示账号不存在
::sendto(pThis->g_s,(char *)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr)); 


}
}
}
//AfxMessageBox(strNo);


}
break;


//[7/15]加为好友
case ADDFRIEND:    
{
CString strFrom,strTo;
strFrom=pMsg->peer.ImNo;
strTo=(char *)(pMsg+1);
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strFrom+"--->"+strTo+" 加为好友";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
//AfxMessageBox(strFrom+"------>"+strTo);
strNo=(char*)(pMsg+1);
vSQL="select * from imuser where ImNo='"+strTo+"' ";
m_record=pThis->ado.GetRecordSet(vSQL);
if(!m_record->adoEOF)
{  
strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");
strIp.TrimRight(" ");
strPort.TrimRight(" ");    
strOnline.TrimRight(" ");
if(strOnline=="1" && strPort!="0")
{
remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);
remoteAddr.sin_port=htons(atoi(strPort));
::sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage)+sizeof(NewFriendMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));
}
else   //没在线,先将离线好友请求添加到数据库中
{
//取得记录集
char *pNo=(char*)(pMsg+1);
vSQL="select * from OffAddfriend";
m_record=pThis->ado.GetRecordSet(vSQL);
m_record->AddNew();                                          ///添加新记录
m_record->PutCollect("ImNo",_variant_t(pNo));              ///为新记录填充ImNo字段


//将离线请求写到数据库
char        *pBuf = buff;
VARIANT        varBLOB;
SAFEARRAY    *psa;
SAFEARRAYBOUND    rgsabound[1];
if(pBuf)
{    
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = dwRecv;                             //存入的数据是去掉用户名的
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);              ///创建SAFEARRAY对象
for (long i = 0; i <(long)dwRecv; i++)
SafeArrayPutElement (psa, &i, pBuf++);                 ///将pBuf指向的二进制数据保存到SAFEARRAY对象psa中


varBLOB.vt = VT_ARRAY | VT_UI1;                           ///将varBLOB的类型设置为BYTE类型的数组
varBLOB.parray = psa;                                     ///为varBLOB变量赋值
m_record->GetFields()->GetItem("ImInfo")->Value=varBLOB;     ///加入BLOB类型的数据

m_record->Update();       
}
}


}
break;


//[8/15]strTo 答应 strFrom 好友请求()
case ADDFRIENDACK:  
{
CString strFrom,strTo;
BOOL bAllow;
NewFriendMessage *pNew=(NewFriendMessage *)(pMsg+1);
strFrom=pNew->szNo;
strTo=pMsg->peer.ImNo;
bAllow=pNew->bAllow;
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strTo+"--->"+strFrom+" 接受加为好友";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
//返回确认消息
vSQL="select * from imuser where ImNo='"+strFrom+"' ";
m_record=pThis->ado.GetRecordSet(vSQL);
if(!m_record->adoEOF)
{  
strNo=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImNo");
strName=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImName");
strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");
strNo.TrimRight(" ");
strName.TrimRight(" ");
strIp.TrimRight(" ");
strPort.TrimRight(" ");    
strOnline.TrimRight(" ");
//先给对方发送
if(bAllow)
{
vSQL="select * from friend where ImNo1='"+strTo+"' and ImNo2='"+strFrom+"' ";
m_record=pThis->ado.GetRecordSet(vSQL);
if(m_record->adoEOF)
{
vSQL="insert into friend values('"+strTo+"','"+strFrom+"')";
pThis->ado.ExecuteSQL(vSQL);
CP2PMessage peerMsg={0};
strcpy((char*)peerMsg.peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)peerMsg.peer.ImName,(LPCSTR)(LPCTSTR)strName);
peerMsg.peer.ImOnline=atoi(strOnline);
peerMsg.nMessageType=ADDFRIENDACK;
::sendto(pThis->g_s,(char*)&peerMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));
}
}
//
vSQL="select * from friend where ImNo1='"+strFrom+"' and ImNo2='"+strTo+"' ";
m_record=pThis->ado.GetRecordSet(vSQL);
if(m_record->adoEOF)
{
vSQL="insert into friend values('"+strFrom+"','"+strTo+"')";
pThis->ado.ExecuteSQL(vSQL);
}
//在给发送方发送确认信息
if(strOnline=="1" && strPort!="0")
{


pMsg->peer.ImOnline=1;
remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);
remoteAddr.sin_port=htons(atoi(strPort));
//直接转发就可以了,消息包中已经包含对方的信息
::sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));


}




}


}
break;


//[9/15]服务器收到客户端节点发给服务器的消息/
case P2PMESSAGE:
{
int nDataLen=dwRecv-sizeof(CP2PMessage)-sizeof(MessageInfo);
if(nDataLen>0)
{   
//发送确认消息
CP2PMessage ackMsg;
ackMsg.nMessageType=P2PMESSAGEACK;
memcpy(&ackMsg.peer,&pThis->m_LocalPeer,sizeof(PEER_INFO));
::sendto(pThis->g_s,(char *)&ackMsg,sizeof(ackMsg),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));


CString strText,strNo,strName;
strName=pMsg->peer.ImName;
strNo=pMsg->peer.ImNo;
strText=strName+"("+strNo+")";
HWND hwnd=pThis->FindMessage(strText);
//找到消息窗口,如果消息窗口存在,则将消息直接传过去,否则弹出提示
if(!hwnd)
{
::SendMessage(g_pPage1->m_hWnd,WM_NEWMESSAGE,(WPARAM)(pMsg+1),(LPARAM)(LPTSTR)(LPCTSTR)strText);
}
else
{
::SendMessage(hwnd,WM_NEWMESSAGE,(WPARAM)(pMsg+1),(LPARAM)(LPTSTR)(LPCTSTR)strText);
}


}
}
break;


//[9/15]收到消息应答
case P2PMESSAGEACK:             
{
pThis->m_bMessageACK=TRUE;
}
break;


//[10/15]语音连接应答
case GETVOIPACK:
{    
//得到从对方返回的监听端口,如果为0.表示对方正在通话中
if(pMsg->peer.p2pAddr.nPort==0)
{
g_strVOIP="0.0.0.0";
//AfxMessageBox("对不起,对方正在通话中,请稍后再拨!");
}
else
{
//保存被叫方的IP和监听端口
g_strVOIP=::inet_ntoa(remoteAddr.sin_addr);
g_nVOIPPort=pMsg->peer.p2pAddr.nPort;


//CString str,str1;
//str.Format("对方的监听端口是:%d\r\n",g_nVOIPPort);
//str1.Format("本地的监听端口是:%d",g_nLocalPort);
//AfxMessageBox(str+str1);
}
}
break;


//[11/15]离线消息
case OFFP2PMESSAGE:
{
DWORD size=dwRecv-sizeof(CP2PMessage)-sizeof(MessageInfo)-MAX_USERNAME;  //消息长,去掉对方的用户名后
MessageInfo *pInfo=(MessageInfo *)(pMsg+1);
char *pNo=(char *)(pInfo+1);
CString strFrom,strTo;
strFrom=pMsg->peer.ImNo;
strTo=pNo;
//写到日志列表中
time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strFrom+"--->"+strTo+" 离线消息";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);
//取得记录集
vSQL="select * from OfflineMessage";
m_record=pThis->ado.GetRecordSet(vSQL);
m_record->AddNew();                                          ///添加新记录
m_record->PutCollect("ImNo",_variant_t(pNo));              ///为新记录填充ImNo字段


memcpy(pNo,pNo+MAX_USERNAME,size);
//将离线消息写到数据库
char        *pBuf = buff;
VARIANT        varBLOB;
SAFEARRAY    *psa;
SAFEARRAYBOUND    rgsabound[1];
if(pBuf)
{    
size=dwRecv-MAX_USERNAME;
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = size;                             //存入的数据是去掉用户名的
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);              ///创建SAFEARRAY对象
for (long i = 0; i <(long)size; i++)
SafeArrayPutElement (psa, &i, pBuf++);                 ///将pBuf指向的二进制数据保存到SAFEARRAY对象psa中


varBLOB.vt = VT_ARRAY | VT_UI1;                           ///将varBLOB的类型设置为BYTE类型的数组
varBLOB.parray = psa;                                     ///为varBLOB变量赋值
m_record->GetFields()->GetItem("ImMsg")->Value=varBLOB;     ///加入BLOB类型的数据

m_record->Update();                                         ///保存我们的数据到库中
}
break;


//[12/15]删除好友///
case DELETEFRIEND:
{
//int nPos=str.Find("(");
//CString strNo=str.Mid(nPos+1,str.GetLength()-nPos-2);
CString strFrom,strTo;
strFrom=pMsg->peer.ImNo;
strTo=(char *)(pMsg+1);   //发过来的消息里含有用户名
int nPos=strTo.Find("(");
strTo=strTo.Mid(nPos+1,strTo.GetLength()-nPos-2);


vSQL="delete from friend where ImNo1='"+strFrom+"' and ImNo2='"+strTo+"'";
if(pThis->ado.ExecuteSQL(vSQL))
{
//写到日志列表中


time=COleDateTime::GetCurrentTime();
strTime=time.Format("%H:%M:%S ");
strLog=strTime+strFrom+"--->"+strNo+" 删除好友";
::PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);


pMsg->nMessageType=DELETEFRIENDACK;
::sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage)+MAX_USERNAME*2,0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));


}


}
break;


//[13/15]得到用户自己信息//
case GETUSERINFO: 
{
strNo=(char *)(pMsg+1);
vSQL="select * from imuser where ImNo='"+strNo+"'";
m_record=pThis->ado.GetRecordSet(vSQL);
if(!m_record->adoEOF)
{


strName=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImName");
strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strPhone=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPhone");


strName.TrimRight(" ");
strIp.TrimRight(" ");
strPort.TrimRight(" ");
strPhone.TrimRight(" ");


//登陆成功,并返回用户自己的信息
pMsg->nMessageType=GETUSERINFOACK;
strcpy((char*)pMsg->peer.ImName,(LPCSTR)(LPCTSTR)strName);
strcpy((char*)pMsg->peer.ImNo,(LPCSTR)(LPCTSTR)strNo);
strcpy((char*)pMsg->peer.ImPhone,(LPCSTR)(LPCTSTR)strPhone);
pMsg->peer.p2pAddr.dwIp=::inet_addr(strIp);
pMsg->peer.p2pAddr.nPort=::atoi(strPort);
pMsg->nMessageType=GETUSERINFOACK;
::sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));




}
}
break;


//[14/15]群聊技术的实现:*关键技术*
case GROUPMESSAGE:
{
strNo=pMsg->peer.ImNo;
vSQL="select ImIp,ImPort,ImOnline from imuser where ImNo!='"+strNo+"'and ImOnline=1";  //只要IP地址和端口号
m_record=pThis->ado.GetRecordSet(vSQL);
while(!m_record->adoEOF)
{
//要发送对象的地址
strIp=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImIp");
strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");
strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");
strIp.TrimRight(" ");
strPort.TrimRight(" ");
strOnline.TrimRight(" ");


remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);
remoteAddr.sin_port=htons(atoi(strPort));
if(strOnline=="1" && strPort!="0")
::sendto(pThis->g_s,(char *)pMsg,dwRecv,0,(sockaddr *)&remoteAddr,sizeof(remoteAddr));
m_record->MoveNext();
}


CString strText,strMessage;
MessageInfo *pInfo=(MessageInfo *)(pMsg+1);
strNo=pMsg->peer.ImNo;
strName=pMsg->peer.ImName;
strText=strName+"("+strNo+") ";
strMessage=(char *)(pInfo+1);


PlaySound("wav\\msg.wav", NULL, SND_FILENAME | SND_ASYNC);
if(g_pDlg->m_pGroupMessage)
{
g_pDlg->m_pGroupMessage->AddName(FALSE,strText);
g_pDlg->m_pGroupMessage->AddText(strMessage+"\r\n",pInfo);
}
else
{    
//群窗口没打开的话,则发送该消息
::SendMessage(g_pDlg->m_hWnd,WM_NEWGROUPMESSAGE,(WPARAM)pMsg,(LPARAM)(LPTSTR)(LPCTSTR)strText);


}


}
break;






}


}
return 0;
}








//查找链表,返回用户名等于 str 的对话框句柄
HWND CP2PServer::FindMessage(CString str)
{
critical_section.Lock();
MessageUser user;
POSITION nPos=g_MessageList.GetHeadPosition();
while(nPos)
{
user=g_MessageList.GetNext(nPos);
if(user.m_strText==str)
{
critical_section.Unlock();
return user.m_hWnd;
}


}
critical_section.Unlock();
return NULL;


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值