/********************************************************* 函数名称:OpenServer 功能描述:初始化服务器 作者: 余志荣 创建日期:2016-08-03 返 回 值:成功返回IDS_SERVER_OPEN_SUCCESS *********************************************************/ int CSocketServerDlg::OpenServer(void) { m_pSocketListen = new CListenSocket(this); if(!AfxSocketInit()) {// 套接字初始化失败 OutputInfo(IDP_SOCKETS_INIT_FAILED); // 输出信息 delete m_pSocketListen; // 清除Socket m_pSocketListen = NULL; // 指针置空 return IDP_SOCKETS_INIT_FAILED; } if(m_pSocketListen->Create(8080) == NULL) {// 绑定端口失败 OutputInfo(IDP_SOCKETS_BIND_FAILED); // 输出信息 delete m_pSocketListen; //清除Socket m_pSocketListen = NULL; return IDP_SOCKETS_BIND_FAILED; } m_pSocketListen->Listen(); //启动监听 SetTimer(123, 10000, NULL); // 定时刷新Socket OutputInfo(IDS_SERVER_OPEN_SUCCESS); // 输出信息 return IDS_SERVER_OPEN_SUCCESS; }
/********************************************************* 函数名称:CheckSocketStatus 功能描述:检查每个Socket 将其中空的和超时的删除掉 创建时间:2016-08-19 参数说明: 返 回 值: *********************************************************/ int CSocketServerDlg::CheckSocketStatus(void) { POSITION pos = m_listSocketChat.GetHeadPosition(); while(pos != NULL) { CChatSocket* p = m_listSocketChat.GetNext(pos); // 删除空Socket if(p == NULL) { if(pos == NULL) {// 空Socket位于链表末尾 m_listSocketChat.RemoveTail(); break; } else { POSITION posTemp = pos; m_listSocketChat.GetPrev(posTemp); m_listSocketChat.RemoveAt(posTemp); } continue; } // 删除超过时间没有通信的Socket int nMaxSec = 30; // 等待的最大时间 CTimeSpan tmsp; tmsp = CTime::GetCurrentTime() - p->m_tmLastMsg; TRACE("%d\n", tmsp.GetTotalSeconds()); if(tmsp.GetTotalSeconds() >= nMaxSec || tmsp.GetSeconds() < 0) { CString csOutMsg; CString csID; csID = p->m_userID; csOutMsg.Format(_T("用户%s连接超时"), csID); OutputInfo(csOutMsg); m_data.SetUserStatus(p->m_userID, IDS_STATUS_OFFLINE); p->Close(); // 关闭连接 delete p; // 释放内存 // 删除元素 if(pos == NULL) {// 空Socket位于链表末尾 m_listSocketChat.RemoveTail(); break; } else { POSITION posTemp = pos; m_listSocketChat.GetPrev(posTemp); m_listSocketChat.RemoveAt(posTemp); } continue; } } return 0; }
// this is FormatMatchesCapabilities for Audio CodecSpecifier* PV2WayMIO::FormatMatchesCapabilities(const PVAsyncInformationalEvent& aEvent) { PVMFFormatType aMimeString; int aMedia_Type = 0; ParseResponse(aEvent, aMimeString, aMedia_Type); // compare to what in iFormats instead. CodecSpecifier* formatInList = FormatInList(aMimeString); if (!formatInList) { OutputInfo("Format %s does not match application capability\n", aMimeString.getMIMEStrPtr()); } else { OutputInfo("Format %s matches application capabilities\n", aMimeString.getMIMEStrPtr()); } return formatInList; }
OSCL_EXPORT_REF PVCommandId PV2WayMIO::Add() { if (iMioNode == 0) return -1; int32 error = 0; if (!iAdded) { /*! Step 11: Add MIO Node to terminal Add appropriate MIO Node to terminal (audio/video, incoming/outgoing) */ if (iMyDir == INCOMING) { OSCL_TRY(error, iAddId = iTerminal->AddDataSink(iChannelId, *iMioNode)); if (error) { OutputInfo("PV2WayMIO::Add():: Error Adding Data Sink!"); } return iAddId; } else { OSCL_TRY(error, iAddId = iTerminal->AddDataSource(iChannelId, *iMioNode)); if (error) { OutputInfo("PV2WayMIO::Add():: Error Adding Data Source!"); } return iAddId; } } else if (!iRemoving) { OutputInfo("\nError: MIO already added!\n"); } else if (iRemoving) { OutputInfo("\nCannot add because attempting to remove MIO!\n"); } return -1; }
OSCL_EXPORT_REF void PV2WayMIO::PrintFormatTypes() { Oscl_Map < PVMFFormatType, CodecSpecifier*, OsclMemAllocator, pvmf_format_type_key_compare_class >::iterator it = iFormatsMap.begin(); if (it == iFormatsMap.end()) { OutputInfo("No formats added."); return; } // loop through each, output values while (it != iFormatsMap.end()) { CodecSpecifier* codec = (*it++).second; PVMFFormatType format = codec->GetFormat(); OutputInfo("%s", format.getMIMEStrPtr()); OutputInfo(" "); } }
OSCL_EXPORT_REF PVCommandId PV2WayMIO::HandleEvent(const PVAsyncInformationalEvent& aEvent) { PVCommandId retvalue = -1; TPVChannelId id = GetIdFromLocalBuffer((PVAsyncInformationalEvent &) aEvent); if (PVT_INDICATION_INCOMING_TRACK == aEvent.GetEventType()) { if (((PVAsyncInformationalEvent&)aEvent).GetLocalBuffer()[0] == PV_VIDEO) { OutputInfo("PVT_INDICATION_INCOMING_TRACK video, id %d\n", id); } else if (((PVAsyncInformationalEvent&)aEvent).GetLocalBuffer()[0] == PV_AUDIO) { OutputInfo("PVT_INDICATION_INCOMING_TRACK audio, id %d\n", id); } } else if (PVT_INDICATION_OUTGOING_TRACK == aEvent.GetEventType()) { if (((PVAsyncInformationalEvent&)aEvent).GetLocalBuffer()[0] == PV_VIDEO) { OutputInfo("PVT_INDICATION_OUTGOING_TRACK video, id %d\n", id); } else if (((PVAsyncInformationalEvent&)aEvent).GetLocalBuffer()[0] == PV_AUDIO) { OutputInfo("PVT_INDICATION_OUTGOING_TRACK audio, id %d\n", id); } } if (iChannelId == id) { OutputInfo("\nDuplicate callback for id %d\n", id); return -1; } if (iChannelId) { OutputInfo("\nBusy ... MIO id=%d being closed\n", iChannelId); iNextChannelId = id; return -1; } if (!iClosing && !iAdded) { iChannelId = id; // format matching capabilities and create- create can tell us which kind to create // including which file we should use, etc. iSelectedCodec = FormatMatchesCapabilities(aEvent); if (iSelectedCodec) { iMioNode = iObserver->CreateMIONode(iSelectedCodec, iMyDir); iMySelectedFormat = iSelectedCodec->GetFormat(); retvalue = Add(); } else { OutputInfo("\nDid not find a codec!!! \n"); } } return retvalue; }
OSCL_EXPORT_REF void PV2WayMIO::AddCompleted(const PVCmdResponse& aResponse) { if (aResponse.GetCmdStatus() == PVMFSuccess) { iAdded = true; } else { OutputInfo("PV2WayMIO::AddCompleted:: Failed to add MIO"); Closed(); } iAddId = -1; }
OSCL_EXPORT_REF int PV2WayDummySourceAndSinks::AddPreferredCodec(TPVDirection aDir, PV2WayMediaType aMediaType, LipSyncDummyMIOSettings& aSettings) { PV2WayMIO* mio = GetMIO(aDir, aMediaType); if (mio) { mio->AddCodec(aSettings); return 0; } OutputInfo("PV2WaySourceAndSinksBase::AddPreferredCodec: Error! No MIO of given dir, type"); return -1; }
OSCL_EXPORT_REF PVCommandId PV2WayMIO::Remove() { int32 error = 0; iRemoving = true; /*! Step 12: Cleanup Step 12a: Remove source and sinks */ if (iMioNode && iRemoveId == -1) { if (iMyDir == INCOMING) { OSCL_TRY(error, iRemoveId = iTerminal->RemoveDataSink(*iMioNode)); if (error) { OutputInfo("\n Error in RemoveDataSink!\n"); } return iRemoveId; } else { OSCL_TRY(error, iRemoveId = iTerminal->RemoveDataSource(*iMioNode)); if (error) { OutputInfo("\n Error in RemoveDataSource!\n"); } return iRemoveId; } } else if (!iAdded) { OutputInfo("\nError: MIO cannot be removed because has not been added!\n"); } return -1; }
/********************************************************* 函数名称:Register 功能描述:用户注册 参数说明:msg-消息结构体 pSocket-接收到消息的pSocket 返 回 值: *********************************************************/ int CSocketServerDlg::Register(struct MSG_REGISTER * msg_reg, CChatSocket * pSocket) { char nID[ID_MAX]; m_data.AddUser(nID, msg_reg); msg_reg->nType = REGISTER_SUCCESS; strcpy_s(msg_reg->nID, nID); if(pSocket->Send(msg_reg, sizeof(*msg_reg)) == 0) {// 发送失败 OutputInfo(IDS_ERR_SOCKETS_SEND_FAILED); return IDS_ERR_SOCKETS_SEND_FAILED; } delete msg_reg; // 释放内存 RefreshListCtrlData(); return 0; }
/********************************************************* 函数名称:LoginOut 功能描述:用户下线 作者: 余志荣 创建日期:2016-08-03 参数说明:msg-消息结构体 pSocket-接收到消息的pSocket 返 回 值: *********************************************************/ int CSocketServerDlg::LoginOut(struct MSG_LOGIN * msg, CChatSocket * pSocket) { // 将状态设置为离线 m_data.SetUserStatus(pSocket->m_userID, IDS_STATUS_OFFLINE); CString csOutMsg; CString csID; csID = msg->nID; csOutMsg.Format(_T("用户%s已退出"), csID); OutputInfo(csOutMsg); // 删除文件socket列表中的指针 POSITION pos = m_FileSocketList.GetHeadPosition(); while (pos != NULL) { CChatSocket *p =m_FileSocketList.GetAt(pos); if(!strcmp(pSocket->m_userID, p->m_userID)) { p->Close(); delete p; m_FileSocketList.RemoveAt(pos); break; } m_FileSocketList.GetNext(pos); } // 删除聊天socket列表中的指针 pos = m_listSocketChat.GetHeadPosition(); while(pos != NULL) { CChatSocket * p = m_listSocketChat.GetAt(pos); if(pSocket == p) { pSocket->Close(); delete pSocket; m_listSocketChat.RemoveAt(pos); break; } m_listSocketChat.GetNext(pos); } // 刷新用户列表 RefreshListCtrlData(); return 0; }
/********************************************************* 函数名称:GetFriendInfo 功能描述:获得好友信息 参数说明:msg-消息结构体 pSocket-接收到消息的pSocket 返 回 值: *********************************************************/ int CSocketServerDlg::GetFriendInfo(struct MSG_USERINFO * msg_userinfo, CChatSocket * pSocket) { struct MSG_USERINFO info; if(m_data.GetUserInfo(info, msg_userinfo->nID) != IDS_ERR_USER_NOT_EXIST) { info.nType = GET_FRIEND_INFO; if(pSocket->Send(&info, sizeof(info)) == 0) {//发送失败 OutputInfo(IDS_ERR_SOCKETS_SEND_FAILED); return IDS_ERR_SOCKETS_SEND_FAILED; } } else {// 查询的用户不存在 } return 0; }
/********************************************************* 函数名称:GetStrangerInfo 功能描述:获得陌生人信息 参数说明:msg-消息结构体 pSocket-接收到消息的pSocket 返 回 值: *********************************************************/ int CSocketServerDlg::GetStrangerInfo(struct MSG_USERINFO * msg_userinfo, CChatSocket * pSocket) { struct MSG_USERINFO info; if(m_data.GetUserPublicInfo(info, msg_userinfo->nID) != IDS_ERR_USER_NOT_EXIST) { info.nType = GET_STRANGER_INFO; if(pSocket->Send(&info, sizeof(info)) == 0) {//发送失败 OutputInfo(IDS_ERR_SOCKETS_SEND_FAILED); return IDS_ERR_SOCKETS_SEND_FAILED; } } else {// 查询的用户不存在 struct MSG_SYS msg_sys; msg_sys.nType = IDS_SYSTEM_MESSAGE; msg_sys.nIDPrompt = IDS_ERR_USER_NOT_EXIST; pSocket->Send(&msg_sys, sizeof(msg_sys)); } return 0; }
/********************************************************* 函数名称:Login 功能描述:用户登录 作者: 余志荣 创建日期:2016-08-03 参数说明:msg-消息结构体 pSocket-接收到消息的pSocket 返 回 值: *********************************************************/ int CSocketServerDlg::Login(struct MSG_LOGIN * msg, CChatSocket * pSocket) { int nRes = m_data.IsCorrect(msg->nID, msg->Key); if(nRes == TRUE)// 检查账号密码正确性 {// 密码正确 if(m_data.GetUserStatus(msg->nID) == IDS_STATUS_OFFLINE) {// 允许登录 // 给客户端返回账号信息 struct MSG_USERINFO msg_info; msg_info.nType = LOGIN_SUCCESS; m_data.GetUserInfo(msg_info, msg->nID); if(pSocket->Send((void *)&msg_info, sizeof(msg_info)) == 0) {//发送失败 OutputInfo(IDS_ERR_SOCKETS_SEND_FAILED); return IDS_ERR_SOCKETS_SEND_FAILED; } strcpy_s(pSocket->m_userID, msg->nID); // 设置pSocket的nID m_data.SetUserStatus(msg->nID, msg->nStatus); RefreshListCtrlData(); // 更新列表控件中的数据 // 在编辑框输出信息 CString csOutMsg; CString csID; csID = msg->nID; csOutMsg.Format(_T("用户%s已连接"), csID); OutputInfo(csOutMsg); } else {// 拒绝登录 原因:重复登录 // 服务器返回信息 告诉客户端登录失败 struct MSG_SYS msg_sys; msg_sys.nType = IDS_SYSTEM_MESSAGE; msg_sys.nIDPrompt = IDS_ERR_ID_HAD_LOGIN; if(pSocket->Send((void *)&msg_sys, sizeof(msg_sys)) == 0) {//发送失败 OutputInfo(IDS_ERR_SOCKETS_SEND_FAILED); return IDS_ERR_SOCKETS_SEND_FAILED; } } } else if(nRes == IDS_ERR_PASSWD_INCORRECT) {// 拒绝登陆 原因:密码错误 // 服务器返回信息 告诉客户端登录失败 struct MSG_SYS msg_sys; msg_sys.nType = IDS_SYSTEM_MESSAGE; msg_sys.nIDPrompt = IDS_ERR_PASSWD_INCORRECT; if(pSocket->Send((void *)&msg_sys, sizeof(msg_sys)) == 0) {//发送失败 OutputInfo(IDS_ERR_SOCKETS_SEND_FAILED); return IDS_ERR_SOCKETS_SEND_FAILED; } } else if(nRes == IDS_ERR_USER_NOT_EXIST) {// 用户不存在 struct MSG_SYS msg_sys; msg_sys.nType = IDS_SYSTEM_MESSAGE; msg_sys.nIDPrompt = IDS_ERR_USER_NOT_EXIST; pSocket->Send(&msg_sys, sizeof(msg_sys)); } return TRUE; }
/********************************************************* 函数名称:RecvMsg 功能描述:接收信息 作者: 余志荣 创建日期:2016-08-03 参数说明:pSocket -- 接收到消息的pSocket 返 回 值:接收到的字节数 *********************************************************/ int CSocketServerDlg::RecvMsg(CChatSocket * pSocket) { int iBufSize = MSG_SIZE_MAX; // 接收的最大字节数 struct MSG_T *msg = new struct MSG_T; int iRes = pSocket->Receive((char *)msg, iBufSize); if(iRes == SOCKET_ERROR) // 接收失败 { //MessageBox(_T("SOCKET_ERROR")); OutputInfo(_T("SOCKET_ERROR")); return 0; } switch(msg->nType) { // 登陆/下线 case LOGIN: // 登录消息 Login((struct MSG_LOGIN *)msg, pSocket); break; case LOGIN_OUT: // 下线消息 LoginOut((struct MSG_LOGIN *)msg, pSocket); break; case GET_FRIEND_LIST: // 请求获得好友列表 GetFriendList((struct MSG_USERINFO *)msg, pSocket);break; case GET_ALL_FRIEND_INFO: // 请求获得全部好友的基本信息 GetAllFriendInfo((struct MSG_FRND_INFO*)msg, pSocket);break; case SET_USER_STATUS: // 设置在线状态 SetUserStatus((struct MSG_USERINFO *)msg, pSocket);break; // 注册 case REGISTER: // 注册消息 Register((struct MSG_REGISTER *)msg, pSocket); break; // 一对一聊天 case GET_FRIEND_INFO: // 请求获得好友信息 GetFriendInfo((struct MSG_USERINFO *)msg, pSocket);break; case CHATING_TEXT_MSG: // 聊天消息 RelayChatMsg((struct MSG_TRANSPOND *)msg, pSocket);break; // 增删好友 case ADD_FRIEND_REQUEST: // 添加好友请求 RelayChatMsg((struct MSG_TRANSPOND *)msg, pSocket);break; case ADD_FRIEND_ANSWER: // 添加请求回应 AddFriend((struct MSG_TRANSPOND *)msg, pSocket);break; case DELETE_FRIEND: // 删除好友 DeleteFriend((MSG_MAKE_FRIEND *)msg, pSocket);break; case GET_STRANGER_INFO: // 请求获得陌生人信息 GetStrangerInfo((struct MSG_USERINFO *)msg, pSocket);break; // 心跳包 case HEARTBEAT: pSocket->Send(msg, sizeof(MSG_SYS)); //TRACE(pSocket->m_userID); //TRACE("\n"); break; // 文件传输 case MESSAGE_FILE_REQUEST: // 发送请求 FileTransRequest((MSG_FILE_REQUEST*)msg); break; case MESSAGE_FILE_AGREE: // 同意发送 case MESSAGE_FILE_REFUSE: // 拒绝发送 case MESSAGE_FILE_ERROR: // 出现错误 FileTransAnswer((MSG_FILE_REQUEST*)msg); break; case FILE_TRANS_SOCKET: strcpy_s(pSocket->m_userID, ((MSG_SYS*)msg)->nID); AddToFileSocketList(pSocket); break; case MESSAGE_FILE_TRANS_BEGIN: case MESSAGE_FILE_TRANS_END: FileTransOpera((MSG_FILE_OPERA *)msg, pSocket); //FileTransRelay((MSG_FILE_REQUEST*)msg);// (未使用) break; case MESSAGE_FILE_CONTENT: FileTransRelay((MSG_FILE_CONTENT*)msg); break; default: //MessageBox(L"未定义的数据类型!"); break; } return iRes; }
/********************************************************* 函数名称:CloseServer 功能描述:关闭服务器 作者: 余志荣 创建日期:2016-09-01 返 回 值:成功返回TRUE *********************************************************/ int CSocketServerDlg::CloseServer(void) { // 断开所有客户端的连接 POSITION pos = m_listSocketChat.GetHeadPosition(); POSITION posTemp; while (pos != NULL) { CChatSocket *pSocket = m_listSocketChat.GetNext(pos); pSocket->Close(); delete pSocket; posTemp = pos; if(posTemp == NULL) { m_listSocketChat.RemoveTail(); } else { m_listSocketChat.GetPrev(posTemp); m_listSocketChat.RemoveAt(posTemp); } /* CChatSocket *pSocket = m_listSocketChat.GetAt(pos); pSocket->Close(); delete pSocket; //m_listSocketChat.RemoveAt(pos); m_listSocketChat.GetNext(pos); */ } pos = m_FileSocketList.GetHeadPosition(); while (pos != NULL) { CChatSocket *pSocket = m_FileSocketList.GetNext(pos); pSocket->Close(); delete pSocket; posTemp = pos; if (pos == NULL) { m_FileSocketList.RemoveTail(); } else { m_FileSocketList.GetPrev(posTemp); m_FileSocketList.RemoveAt(posTemp); } /* CChatSocket *pSocket = m_FileSocketList.GetAt(pos); pSocket->Close(); delete pSocket; //m_FileSocketList.RemoveAt(pos); m_FileSocketList.GetNext(pos); */ } // 关闭监听 m_pSocketListen->Close(); delete m_pSocketListen; m_pSocketListen = NULL; OutputInfo(L"关闭服务成功。"); return TRUE; }