C++写的一个聊天室代码,用于XEIM开源即时通讯软件上的

    技术2026-01-17  5

    // C++写的一个聊天室代码,用于XEIM开源即时通讯软件上的,欢迎大家一起交流。

    // XEIM_ChatroomDlg.cpp : implementation file// [即时通讯软件],[XEIM],[飞鸽传书]

    #include "stdafx.h"#include "xeim.h"#include "xeimDlg.h"#include "XEIM_ChatroomDlg.h"#include "XEIM_Text.h"#include "XEIM_Message.h"#include "XEIM_ChatDlg.h"

    #ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif

    /// CXEIM_ChatroomDlg dialog

    CXEIM_ChatroomDlg::CXEIM_ChatroomDlg(CWnd* pParent /*=NULL*/) : CDialog(CXEIM_ChatroomDlg::IDD, pParent){ //{{AFX_DATA_INIT(CXEIM_ChatroomDlg)  // NOTE: the ClassWizard will add member initialization here m_bServerRunning = FALSE; m_hServer = INVALID_HANDLE_VALUE; //}}AFX_DATA_INIT m_hIcon = AfxGetApp()->LoadIcon(IDI_ICONCHAT);}

    CXEIM_ChatroomDlg::CXEIM_ChatroomDlg(LPCTSTR lpszUID, CWnd* pParent/* = NULL*/){ m_hIcon = AfxGetApp()->LoadIcon(IDI_ICONCHAT); m_bServerRunning = FALSE; m_hServer = INVALID_HANDLE_VALUE; CString strUID = lpszUID; if (! strUID.IsEmpty()) {  m_bServerRunning = TRUE;  if (! m_client.xConnect(M()->T.GetContactIP(lpszUID), 9989))  {   MessageBox(m_client.m_strLastError);   return;  }  else  {   DWORD dwTID;   m_client.SetWnd(this);   HANDLE hThread = CreateThread(NULL, 0, SockRecvProc, (LPVOID)&m_client, 0, & dwTID);   if (NULL == hThread)   {    MessageBox("CreateThread(NULL, 0, CreateHTML_Proc, (LPVOID)m_client, 0, & dwTID) failed.");    return;   }   m_mapClient.insert(pair<HANDLE, CXEIMSocket*>(hThread, &m_client));  } }}

    void CXEIM_ChatroomDlg::AddRecvText(LPCTSTR lpszUser, LPCTSTR lpszData){ CTime m_StartTime1 = CTime::GetCurrentTime(); CString csStartTime; // 信息 发送者 和 发送时间 csStartTime.Format(_T("%s - %s/r/n"), M()->T.GetContactDisplayName(lpszUser),  m_StartTime1.Format(_T("%H:%M:%S")));

     // int iTotalTextLength = m_richMsg.GetWindowTextLength(); m_richMsg.SetSel(iTotalTextLength, iTotalTextLength); m_richMsg.ReplaceSel(csStartTime); int iStartPos = iTotalTextLength; CHARFORMAT cf; cf.cbSize = sizeof(CHARFORMAT); cf.dwMask = CFM_COLOR | CFM_UNDERLINE | CFM_BOLD; cf.dwEffects = (unsigned long)~(CFE_AUTOCOLOR | CFE_UNDERLINE | CFE_BOLD); cf.crTextColor = RGB(0, 128, 0); int iEndPos = m_richMsg.GetWindowTextLength(); m_richMsg.SetSel(iStartPos, iEndPos); m_richMsg.SetSelectionCharFormat(cf); m_richMsg.SetSel(iEndPos, iEndPos); CString str = lpszData;

     int nIdx = 0; while (nIdx != -1) {  nIdx = str.Find('/n', nIdx+1);  str.Insert(nIdx+1, "  "); } str += "/r/n";

     m_richMsg.ReplaceSel(str); m_richMsg.SetSel(iEndPos, m_richMsg.GetWindowTextLength()); cf.crTextColor = RGB(0, 0, 0); m_richMsg.SetSelectionCharFormat(cf); m_richMsg.PostMessage(WM_VSCROLL, SB_BOTTOM,0);

    /* m_editAllMessage += lpszUser; m_editAllMessage += "/r/n"; m_editAllMessage += lpszData; UpdateData(FALSE); AfxMessageBox(lpszData);*/}

    void CXEIM_ChatroomDlg::OnAcceptClose(){// AfxMessageBox("asdf");}

    void CXEIM_ChatroomDlg::OnRecvData(WPARAM wParam, LPARAM lParam){ CXEIMSocket *pclient = (CXEIMSocket*)lParam; CXEIMData *pData = (CXEIMData*)wParam;

    // AfxMessageBox(pData->GetData()); if (pData->GetMessage() == 2) {  CString strData = pData->GetData();  UINT nLeft = strData.Find("|");  CString strUID = strData.Left(nLeft);  CString strText = strData.Right(strData.GetLength()-nLeft-1);  AddRecvText(strUID, strText);

      if (m_bServerRunning) {

       map<HANDLE, CXEIMSocket*>::iterator _beg=m_mapClient.begin(),    _end=m_mapClient.end();

       for (; _beg != _end; _beg++)   {    _beg->second->xSend(pData->GetData(), pData->GetDataLength());   }  } } else if (pData->GetMessage() == 1) {  CString strData = pData->GetData();  CString strRight = strData;  UINT nIdx = strData.Find("|");  while (-1 != nIdx)  {   CString strUser = strRight.Left(nIdx);   m_listboxUser.AddString(strUser);   CString strk;   strk.Format("%s - %d,%d",strData, nIdx, strData.GetLength());   strRight = strRight.Right(strRight.GetLength()-nIdx-1);   nIdx = strRight.Find("|");  } }

     delete pData;}

    void CXEIM_ChatroomDlg::OnNewClient(WPARAM wParam, LPARAM lParam){ CXEIMSocket *pClient = new CXEIMSocket((SOCKET)wParam, (CWnd*)lParam);

     DWORD dwTID; HANDLE hThread = CreateThread(NULL, 0, SockRecvProc, (LPVOID)pClient, 0, & dwTID); if (NULL == hThread) {  MessageBox("CreateThread(NULL, 0, CreateHTML_Proc, (LPVOID)this, 0, & dwTID) failed.");  return; } m_mapClient.insert(pair<HANDLE, CXEIMSocket*>(hThread, pClient));

     CString strUsers; int nCount = m_listboxUser.GetCount(); // 得到项目总数 for(int i=0; i<nCount; ++ i) {  CString strText;  m_listboxUser.GetText(i, strText);  strUsers += strText;  strUsers += "|"; } pClient->xSend1(strUsers, strUsers.GetLength()+1);// MessageBox(pClient->GetHostAddress());}

    void CXEIM_ChatroomDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CXEIM_ChatroomDlg) DDX_Control(pDX, IDC_RICHEDIT1, m_richMsg); DDX_Control(pDX, IDC_LIST1, m_listboxUser); //}}AFX_DATA_MAP}

    BEGIN_MESSAGE_MAP(CXEIM_ChatroomDlg, CDialog) //{{AFX_MSG_MAP(CXEIM_ChatroomDlg) ON_MESSAGE(WM_SERVER_CREATED, OnServerCreated) ON_MESSAGE(WM_ACCEPT_CLOSE, OnAcceptClose) ON_MESSAGE(WM_NEW_CLIENT, OnNewClient) ON_MESSAGE(WM_RECV_DATA, OnRecvData) ON_BN_CLICKED(IDC_SEND, OnSend) ON_MESSAGE(XM_EMDBLCLICKTREE, XDoubleClickUserList) //}}AFX_MSG_MAPEND_MESSAGE_MAP()

    /// CXEIM_ChatroomDlg message handlers

    void CXEIM_ChatroomDlg::OnOK() { // TODO: Add extra validation here CDialog::OnOK();}

    void CXEIM_ChatroomDlg::OnCancel() { // TODO: Add extra cleanup here  CDialog::OnCancel();}

    void CXEIM_ChatroomDlg::OnSend() { // TODO: Add your control notification handler code here/* UpdateData(); if (m_editSend.IsEmpty()) {  AfxMessageBox("请输入要发送的消息");  return; }

     if (! m_bServerRunning) { // 客户端  m_client.xSend(m_editSend, m_editSend.GetLength()+1); } else // 服务端 {  map<HANDLE, CXEIMSocket*>::iterator _beg=m_mapClient.begin(),   _end=m_mapClient.end();  for (; _beg != _end; _beg++)  {   _beg->second->xSend(m_editSend, m_editSend.GetLength()+1);  }  AddRecvText("Server", m_editSend); }

     m_editSend = ""; UpdateData(FALSE);*/ CString str; GetDlgItemText(IDC_RICHEDIT2, str); if(str.IsEmpty()) {  MessageBox("请输入消息内容!");  return; } if (str.GetLength() > 1024 - 100) {  CString str2;  str2.Format(_T("你所发的信息太长,请分几次发送,最大 1024 个字符。"), str.GetLength());  MessageBox(str2, _T("警告"), MB_ICONINFORMATION);  return; }

     CString strSend; strSend.Format(_T("%s|%s"), M()->T.GetLocalUID(), str);

     if (! m_bServerRunning) {  m_client.xSend(strSend, strSend.GetLength()+1); } else {  map<HANDLE, CXEIMSocket*>::iterator   _beg=m_mapClient.begin(),   _end=m_mapClient.end();

      for (; _beg != _end; _beg++)  {   _beg->second->xSend(strSend, strSend.GetLength()+1);  }

      AddRecvText(M()->T.GetLocalUID(), str); }

     SetDlgItemText(IDC_RICHEDIT2, "");// m_client.xSend("33",3);}

    void CXEIM_ChatroomDlg::OnServerCreated(WPARAM wParam, LPARAM lParam){ XEIM _p = M();

     CString strFileString; strFileString.Format(_T("%s|%s"), XEIM_CHATROOM, m_strChatroomName);

    /* map<HTREEITEM, XEIM_User*>::iterator imap  = _p->m_chatroomUsers.begin(),  _end = _p->m_chatroomUsers.end();

     // 读取聊天室成员 for (; imap!=_end; ++imap) {

      CXEIM_Text xText(imap->second->GetUID(), strFileString);  // 获取用户联系人  XEIM_Message toSend("forward",xText.GetBuffer()); // AfxMessageBox(toSend.GetData());  if(! _p->m_iocp.BuildPackageAndSend(_p->m_serverSocket,Job_UserData,toSend.GetBuffer()))  {   AfxMessageBox("Send not successfull.!");  }

     // int nIndex = m_listboxUser.AddString(imap->second->GetDisplayName()); // m_listboxUser.SetItemData(nIndex, imap->first); }*/}

    BOOL CXEIM_ChatroomDlg::OnInitDialog() { CDialog::OnInitDialog();  // Set the icon for this dialog.  The framework does this automatically //  when the application's main window is not a dialog SetIcon(m_hIcon, TRUE);   // Set big icon SetIcon(m_hIcon, FALSE);  // Set small icon

     // TODO: Add extra initialization here

     // 设置聊天室名称 CString strRoomname; strRoomname.Format(_T("%s - 聊天室"), m_strChatroomName); SetWindowText(strRoomname);

     // 创建 聊天室服务器 线程/* if (! m_bServerRunning) {  // 聊天是首先要有自己  CString strSelfName = M()->GetLocalDisplayName();  strSelfName += _T("(主机)");  int nIndex = m_listboxUser.AddString(strSelfName);  m_listboxUser.SetItemData(nIndex, 0);

      m_bServerRunning = TRUE;

      DWORD dwTID;  m_hServer = CreateThread(NULL, 0, ServerThreadProc, (LPVOID)this, 0, & dwTID);  if (NULL == m_hServer)  {   AfxMessageBox("CreateThread(NULL, 0, CreateHTML_Proc, (LPVOID)this, 0, & dwTID) failed.");   return TRUE;  }

      map<SOCKET, XEIM_User*>::iterator imap  = M()->m_chatroomUsers.begin(),  _end = M()->m_chatroomUsers.end();

      // 读取聊天室成员  for (; imap!=_end; ++imap) {   int nIndex = m_listboxUser.AddString(imap->second->GetDisplayName());   m_listboxUser.SetItemData(nIndex, imap->first);  } } else {  m_bServerRunning = ! m_bServerRunning; }*/ return TRUE;  // return TRUE unless you set the focus to a control               // EXCEPTION: OCX Property Pages should return FALSE}

     

    DWORD CALLBACK CXEIM_ChatroomDlg::SockRecvProc(LPVOID lParam){ CXEIMSocket *pclient = (CXEIMSocket*)lParam; CXEIM_ChatroomDlg *pDlg = (CXEIM_ChatroomDlg*)pclient->GetWnd();

    // ::MessageBox(NULL,"","",MB_OK); while(1) {  UINT nLen = 0;  char * buf = pclient->xRecv(nLen);  if (nLen > 0)  {   CXEIMData *pData = new CXEIMData(buf, nLen);   if (pDlg)    pDlg->PostMessage(WM_RECV_DATA, (WPARAM)pData, (LPARAM)pclient);  }  delete buf; }

     pclient->xShutdown(SD_BOTH); pclient->xCloseSocket();

     return -1;}

    DWORD CALLBACK CXEIM_ChatroomDlg::ServerThreadProc(LPVOID lParam){ CXEIM_ChatroomDlg *pDlg = (CXEIM_ChatroomDlg*)lParam;

        //最好不要使用aSocket.Create创建,因为容易会出现10048错误 pDlg->m_svrSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    if (INVALID_SOCKET == pDlg->m_svrSocket)    {        char szError[256] = {0};        sprintf(szError, "Create Faild: %d", WSAGetLastError());        AfxMessageBox(szError);        return -1;    }

        BOOL bOptVal = TRUE;    int bOptLen = sizeof(BOOL);    //设置Socket的选项, 解决10048错误必须的步骤 setsockopt(pDlg->m_svrSocket, SOL_SOCKET, SO_REUSEADDR, (LPSTR)&bOptVal, bOptLen);

       // pDlg->m_svrSocket.SetSockOpt(SO_REUSEADDR, (void *)&bOptVal, bOptLen, SOL_SOCKET); SOCKADDR_IN local; memset(&local, 0, sizeof(SOCKADDR_IN)); local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(9989);

     int ret = bind(pDlg->m_svrSocket, (PSOCKADDR)&local, sizeof(SOCKADDR_IN));

     //绑定端口    if (SOCKET_ERROR == ret)    {        char szError[256] = {0};        sprintf(szError, "Bind Faild: %d", WSAGetLastError());        AfxMessageBox(szError);        return -1;     }

        //监听 ret = listen(pDlg->m_svrSocket, 10);    if(SOCKET_ERROR == ret)    {        char szError[256] = {0};        sprintf(szError, "Listen Faild: %d", WSAGetLastError());        AfxMessageBox(szError);        return -1;    }

     // 通知上级线程 线程服务可以开始了 pDlg->PostMessage(WM_SERVER_CREATED);

     while (pDlg->m_bServerRunning) {  // 接收外部连接  int iAddress = sizeof(SOCKADDR_IN);  SOCKET sClient;  SOCKADDR_IN addrClient;  memset(&addrClient, 0, sizeof(SOCKADDR_IN));  sClient = accept(pDlg->m_svrSocket, (PSOCKADDR)&addrClient, &iAddress);        if (INVALID_SOCKET == sClient)        {  // AfxMessageBox("delete pClient");   pDlg->PostMessage(WM_ACCEPT_CLOSE, 0, 0);            break;        }        else        {   pDlg->PostMessage(WM_NEW_CLIENT, (WPARAM)sClient, (LPARAM)lParam);  // char szRecvMsg[256] = {0};  // char szOutMsg[256] = {0};

       //接收客户端内容:阻塞  // sClient.Receive(szRecvMsg, 256);  // sprintf(szOutMsg, "Receive Msg: %s  ", szRecvMsg);  // AfxMessageBox("");

      // pDlg->GetDlgItemText(IDC_EDIT_LOG, strText);  // strText += szOutMsg;   //aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);

       //发送内容给客户端  // serverSocket.Send("Have Receive The Msg", 50);

       //关闭  // sClient.Close();  // serverSocket.Close();        } }

     return -1;}

    void CXEIM_ChatroomDlg::ShowAndUpdate(){ PostMessage(XM_EMDBLCLICKTREE);}

    void CXEIM_ChatroomDlg::XDoubleClickUserList(WPARAM wParam, LPARAM lParam){ ShowWindow(SW_SHOW); GetDlgItem(IDC_RICHEDIT2)->SetFocus();}

    最新回复(0)