您的位置:首页 > 教育 > 锐评 > 廊坊视频优化效果_北京综合网络营销_百度推广官方_怎么去推广一个app

廊坊视频优化效果_北京综合网络营销_百度推广官方_怎么去推广一个app

2025/5/8 16:10:37 来源:https://blog.csdn.net/qq_59940419/article/details/144475397  浏览:    关键词:廊坊视频优化效果_北京综合网络营销_百度推广官方_怎么去推广一个app
廊坊视频优化效果_北京综合网络营销_百度推广官方_怎么去推广一个app

文章目录

  • 前言
  • 一、添加客户端队列的参数初始化
  • 二、相关函数
  • 总结


前言

C++打造局域网聊天室第九课: 客户端队列及其处理线程


一、添加客户端队列的参数初始化

在Server.cpp的 ListenThreadFunc()函数内的其他操作处实现客户端队列的添加。
在这里插入图片描述
首先进行部分参数的初始化

CClientitem tItem; //定义一个客户端结点
tItem.m_Socket = accSock; //客户端的socket即为accept函数返回的accSock
tItem.m_surlp = inet_ntoa(clientAddr.sin_addr); // 客户端的IP包含在clientAddr结构中。inet_ntoa()函数将网络字节顺序的Ip转化为本机格式的字符串(192.192.1.1)
tItem.m_pMainWnd = pChartRoom; //主线程对话框指针

此时编译会报错: ‘inet_ntoa’: Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings chartroom d:\vs2017项目\打造局域网聊天室\chartroom\chartroom\server.cpp 100

这是由于函数inet_ntoa过旧,此时需要在项目的属性中把SDL检查设置为否。
在这里插入图片描述

二、相关函数

后续的客户端队列的建立过程需要依赖一些函数,我们先实现这些函数,再回来继续客户端队列的建立过程。

聊天信息显示函数:
由于服务端每次都需要显示全部的聊天记录,而不是只显示当前的聊天记录,这就需要我们对之前的聊天内容进行保存。
首先对显示聊天内容的编辑框绑定一个成员变量。
在这里插入图片描述
设置一个变量名称,其他都为默认值
在这里插入图片描述
此时在chartroomDlg.h头文件内会自动声明该变量。
在这里插入图片描述
并且在chartroomDlg.h头文件中声明一个函数,用于声明聊天信息显示函数
在这里插入图片描述
在chartroomDlg.cpp源文件中实现函数ShowMsg()

// 实现聊天信息显示函数
void CchartroomDlg::ShowMsg(CString strMsg)
{m_MsgEdit.SetSel(-1, -1); // 将光标定位到文字的最后一个位置m_MsgEdit.ReplaceSel(strMsg + _T("\r\n")); // 将光标替换为strMsg + _T("\r\n")
}

从队列中删除客户端函数:
如果客户端关闭,此时服务端对应的客户端结点还在客户端队列中,那么就需要将客户端结点从客户端队列中删除。

同样先在chartroomDlg.h头文件内声明函数,使得类CchartroomDlg中包含成员函数
在这里插入图片描述
在chartroomDlg.cpp源文件中实现函数RemoveClientFromArray()

// 实现从队列删除客户端结点函数
void CchartroomDlg::RemoveClientFromArray(CClientitem in_Item) //参数为需要删除的客户端结点
{for (int idx = 0; idx < m_ClientArray.GetCount(); idx++) // 遍历客户端队列中的每一个结点{CClientitem tItem = m_ClientArray.GetAt(idx);if (tItem.m_Socket == in_Item.m_Socket && tItem.hThread == in_Item.hThread && tItem.m_surlp == in_Item.m_surlp) //队列中的该结点为需要删除的结点{m_ClientArray.RemoveAt(idx); // 删除结点}}
}

现在我们回到Server.cpp文件中,继续客户端队列的建立过程。
接下来初始化该客户端结点的线程句柄,同服务端创建线程,利用函数 CreateThread()。

// 客户端队列的添加CClientitem tItem; //定义一个客户端结点tItem.m_Socket = accSock; //客户端的socket即为accept函数返回的accSocktItem.m_surlp = inet_ntoa(clientAddr.sin_addr); // 客户端的IP包含在clientAddr结构中。inet_ntoa()函数将网络字节顺序的Ip转化为本机格式的字符串(192.192.1.1)tItem.m_pMainWnd = pChartRoom; //主线程对话框指针//  每一个客户端对应线程的句柄。说明:一个服务端对应多个客户端,在while死循环中调用accept接受一个客户端的连接之后,还可以在其他循环时接受// 其他客户端连接,每有一个客户端连接,我们创建一个客户端结点,将客户端结点的信息加入到客户端队列当中。//!!!!!!!!注意:该线程只进行监听端口,等待连接客户端的操作,接受连接客户端传来的消息等功能还需要新开一个线程进行处理,新开的线程与连接的客户端进行通信INT_PTR idx = pChartRoom->m_ClientArray.Add(tItem); // 将客户端结点放入队列中tItem.hThread = CreateThread(NULL, 0, ClientThreadProc, &(pChartRoom->m_ClientArray.GetAt(idx)), CREATE_SUSPENDED, NULL);// 初始化该客户端结点的线程句柄,注意第四个参数不要传递tItem的地址,CREATE_SUSPENDED表示该线程不要立即执行//这是因为如果有多个客户端来连接,tItem会一直变为最新连接的客户端结点,但是之前调用的以前连接的客户端结点也是用tItem,此时tItem已经存储的没有//之前连接的客户端结点的内容了pChartRoom->m_ClientArray.GetAt(idx).hThread = tItem.hThread; //将tItem的线程句柄同时赋给客户端队列中对应的客户端的线程句柄// 至此,该客户端的结点信息填充完毕ResumeThread(tItem.hThread); //与CREATE_SUSPENDED对应,在这里才开始执行被CREATE_SUSPENDED修饰的线程

下面介绍该线程的程序ClientThreadProc()函数的具体实现

// 实现客户端的创建线程函数,与接受的客户端进行通信的线程函数
DWORD WINAPI ClientThreadProc(LPVOID IpParameter) // 传入的参数为&(pChartRoom->m_ClientArray.GetAt(idx))
{CString strMsg;CClientitem m_ClientItem = *(CClientitem*)IpParameter; // 将传入的地址利用强制类型转换为客户端结点类型,不使用地址是怕误修改while (TRUE) // 用于监听该连接的客户端是否发送消息{if (SOCKET_Select(m_ClientItem.m_Socket, 100, TRUE)) //向缓冲区“偷看”一眼是否有客户端发过来的消息{TCHAR szBuf[MAX_BUF_SIZE] = { 0 }; // 申请缓冲区// recv函数:第一个参数为接收哪一个socket的数据;第二个参数为窄字节的缓冲区,存放接收过来的数据,要申请一块内存//第三个参数:缓冲区的长度;第四个参数平时为0即可。正常返回接收字节个数int iRet = recv(m_ClientItem.m_Socket, (char*)szBuf, MAX_BUF_SIZE,0); // 调用recv函数接受缓冲区中客户端发过来的消息if (iRet > 0){//正确,接收数据成功strMsg = szBuf; //为了操作方便(使用模板类函数),这里我们使用CString类型strMsg = _T("客户端:") + m_ClientItem.m_surlp + _T(">") + strMsg;m_ClientItem.m_pMainWnd->ShowMsg(strMsg); //利用在chartroom.cpp中实现的ShowMsg方法将信息显示}else // 接收数据失败,有错误或者客户端关闭了{// 关闭socketstrMsg = _T("客户端") + m_ClientItem.m_surlp + _T("离开了聊天室!");m_ClientItem.m_pMainWnd->ShowMsg(strMsg); //利用在chartroom.cpp中实现的ShowMsg方法将信息显示m_ClientItem.m_pMainWnd->RemoveClientFromArray(m_ClientItem); // 利用在chartroom.cpp中实现的RemoveClientFromArray方法在客户端队列中删去该客户端结点break;// 跳出循环,客户端已下线,退出线程}}Sleep(500);}return TRUE;
}

总结

C++打造局域网聊天室第九课: 客户端队列及其处理线程

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com