




已阅读5页,还剩22页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于 TCP 协议编程的网络聊天室设计内容:基于 TCP 协议编程的方式,编写程序模拟网络聊天室的运行过程。设计要求:1. 采用 C/S 模式,基于 TCP 协议编程的方式,使得各个用户通过服务器转发实现聊天的功能。2. 分为两大模块:客户端模块和服务器端模块。3. 客户端模块的主要功能:1)登陆功能:用户可以注册,然后选择服务器登入聊天室。2)显示用户:将在线用户显示在列表中。3)接收信息:能接收其他用户发出的信息。4)发送信息:能发出用户要发出的信息。4.服务器端模块的主要功能:1)检验登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就允许用户登陆。2)显示在线状态:将该用户的状态发给各在线用户。3)转发聊天信息:将消息转发给所有在线的用户。5. 编程语言不限。一、 需求分析此 程 序 主 要 分 为 两 部 分 : 服 务 器 端 和 客 户 端 。服务器端用于提供一个网络端口,等待客户端发出请求,登录到此服务端,然后进行网络通讯和消息的转发;客户端可通过服务器端的 IP 地址发送连接请求,然后登陆聊天室。在服务器端的成员列表栏中会显示在线的所有人名单,有人退出聊天室,成员列表会自动除名。整个程序的主体使用了 CSocket类的方法,实现了网络通讯聊天。整个程序设计为两个部分:服务器(SpeakerServer)和客户端 (SpeakerClient) 。 多人聊天的关键在于要将每个客户端发送过来的消息分发给所有其他客户端,为了解决这个问题,在服务器程序中建立一个套接口链表,用来保存所有与客户端建立了连接的服务端口。设计原理:服务器通过 socket()系统调用创建一个 Socket 数组后(设定了接受连接客户的最大数目),与指定的本地端口绑定 bind(),就可以在端口进行侦听 listen()。如果有客户端连接请求,则在数组中选择一个空 socket,将客户端地址赋给这个 socket,然后登陆成功的客户就可以在服务器上聊天了。客户端程序相对简单,只要建立一个 socket 与服务器端连接,成功后通过这个 socket 来发送和接收就可以了。服务器端功能:1、 初始化 socket,创建服务器端。2、 维护一个链表,保存所有用户的 IP 地址,端口信息。3、 接受用户传送来的聊天信息,然后向链表中的所用用户转发。4、 接受用户传送来的连接判断命令,并向用户发出响应命令。客户端功能:客户端界面上的两个文本框,一个用于显示接受的聊天信息,一个用来接受用户输入的聊天信息。当按下“发送”按钮时将信息发送给服务器。一、 概要设计:服务器 客户端(设计流程图)二、 详细设计:服务器端:1、启动服务器代码:/服务器启动时,先创建套接字并绑定端口,再监听此端口。void CSpeakerServerDlg:OnBnClickedStart()UINT uPort = GetDlgItemInt(IDC_PORT);/创建套接字if ( !m_TCPSocketListen.Create(uPort) )m_TraceRichEdit.TraceString(TEXT(“绑定监听端口失败,请确认该端口没有被其它程序占用“),TraceLevel_Warning);return;/监听套接字if( !m_TCPSocketListen.Listen() )m_TraceRichEdit.TraceString(TEXT(“监听失败“),TraceLevel_Warning);return;UINT uMaxConnect = GetDlgItemInt(IDC_MAX);/设置接口m_TCPSocketListen.SetTCPSocketService(this);/更新界面m_TraceRichEdit.TraceString(TEXT(“服务器启动成功“),TraceLevel_Normal);GetDlgItem(IDC_START)-EnableWindow(FALSE);GetDlgItem(IDC_STOP)-EnableWindow(TRUE);2、监听端口,收到连接请求,接受的代码:/先检验是否在服务器的最大连接限制内,若在,则获取当前客户的 IP 地址和端口等信息,插入链表中。/为什么要限制连接人数?因为 TCP 连接是相当占资源的,若不限制连接人数,服务器的资源不够分配。void CSpeakerServerDlg:OnAccept()/承载能力if ( m_TCPSocketItemMap.size() GetDlgItemInt(IDC_MAX) )m_TraceRichEdit.TraceString(TEXT(“服务器承载人数已满,已过滤其他连接“),TraceLevel_Warning);return;/绑定套接字CTCPSocketService *pTCPSocketConnect = new CTCPSocketService;trySOCKADDR_IN SocketAddr;int nBufferSize = sizeof(SocketAddr);/连接m_TCPSocketListen.Accept(*pTCPSocketConnect,(SOCKADDR *) if (pTCPSocketConnect-m_hSocket = INVALID_SOCKET) throw TEXT(“无效的连接套接字“);/获取客户端 IPpTCPSocketConnect-m_dwClientAddr = SocketAddr.sin_addr.S_un.S_addr;pTCPSocketConnect-SetTCPSocketService(this);/绑定数据bool bActive = true;CTCPSocketItemMap:iterator iter = m_TCPSocketItemMap.begin();for (;iter!= m_TCPSocketItemMap.end();iter+)if ( pTCPSocketConnect-m_hSocket = iter-first )bActive = false;break;/插入客户数据if ( bActive )tagBindParameter *pBindParameter = new tagBindParameter;pBindParameter-pTCPSocketService = pTCPSocketConnect;pBindParameter-dwUserID = 0;m_TCPSocketItemMap.insert(pair(pTCPSocketConnect-m_hSocket,pBindParameter);catch (.)if (pTCPSocketConnect-m_hSocket != INVALID_SOCKET) pTCPSocketConnect-Close();3、接收并检验数据的代码:void CSpeakerServerDlg:OnReceive(SOCKET hSocket)BYTE cbDataBufferSOCKET_TCP_BUFFER;CTCPSocketItemMap:iterator iter = m_TCPSocketItemMap.find(hSocket);if ( iter = m_TCPSocketItemMap.end() ) return;/接收数据iter-second-pTCPSocketService-Receive(cbDataBuffer,CountArray(cbDataBuffer) );/解析数据TCP_Command * pCommand=(TCP_Command *)cbDataBuffer;/解释数据WORD wPacketSize = pCommand-wPacketSize;WORD wDataSize = wPacketSize-sizeof(TCP_Command);/数据包效验if ( wPacketSize SOCKET_TCP_BUFFER+sizeof TCP_Command )m_TraceRichEdit.TraceString(TEXT(“数据包太大,已拒绝“),TraceLevel_Warning);return;/子消息处理事件if( !OnEventTCPSocketRead(hSocket,pCommand-wMainCmdID,pCommand-wSubCmdID,pCommand+1,wDataSize) )BYTE * pClientIP=(BYTE *)m_TraceRichEdit.TraceString(TraceLevel_Warning,TEXT(“收到伪数据包或未处理的数据包,wMainCmdID:%d,wSubCmdID:%d,来源 IP:%d.%d.%d.%d“),pCommand-wMainCmdID,pCommand-wSubCmdID,pClientIP0,pClientIP1,pClientIP2,pClientIP3);return;4、群发登录消息和用户发送的消息代码:/服务器收到客户的消息之后会将收到的消息发送给链表之中除了发送客户之外的所有客户。bool CSpeakerServerDlg:OnEventTCPSocketRead( SOCKET hSocket,WORD wMainCmdID, WORD wSubCmdID, VOID * pData, WORD wDataSize )/获取绑定套接字CTCPSocketItemMap:iterator iter = m_TCPSocketItemMap.find(hSocket);if ( iter = m_TCPSocketItemMap.end() ) return false;CTCPSocketService *pTCPSocketService = iter-second-pTCPSocketService;switch ( wMainCmdID )case MDM_GP_LOGON:if ( wSubCmdID = SUB_CS_LOGON )/效验数据ASSERT( wDataSize = sizeof CMD_CS_LOGON );if ( wDataSize != sizeof CMD_CS_LOGON ) return false;/获取数据CMD_CS_LOGON *pUserLogon = (CMD_CS_LOGON*)pData;m_TraceRichEdit.TraceString(TraceLevel_Normal,TEXT(“%s 登陆服务器“),pUserLogon-szUserName);tagUserData *pUserData = new tagUserData;/随机给用户分配一个 UserID,UserID 一般存储于数据库中,是一个独一无二的数字,/一般在数据库表中设为主键,是整个游戏或者软件识别用户的唯一依据,这里我们没有涉及到数据库,暂时随机取一个数值代替/其次,我们应该通过数据库 SQL 语句查询或者存储过程等方法,或在数据库中做密码的效验也好,/或在查询到用户的密码在服务器中进行判断也好,不管什么方法,此处一般需要进行用户密码的效验,这样才可以判定用户是否可以登陆了pUserData-dwUserID = GetTickCount();_sntprintf_s(pUserData-szUserName,CountArray(pUserData-szUserName),pUserLogon-szUserName);_sntprintf_s(pUserData-
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024-2025学年河北省石家庄市高新区冀教版(三起)(2012)五年级下册期末测试英语试卷(含答案)
- 石家庄市第四十中学2026届高一化学第一学期期末调研模拟试题含解析
- 2025年金属非金属矿山安全检查(露天矿山)新版试题库附答案
- 职员个人在职工作阶段方案
- 2025年教师资格证考试教师职业道德模拟考试题及答案
- 市政养护安全知识培训课件
- 关于影城劳动节活动方案
- 1.1菱形的性质与判定 预习练(含解析)北师版数学九年级上册
- 山西省晋中市祁县一中2026届化学高二上期末检测模拟试题含答案
- 2025年教师资格考试小学面试全科试题与参考答案
- 老年呼吸系统疾病及护理
- 施工现场生态环境保护措施
- 2024年江苏省阜宁县安监局公开招聘试题含答案分析
- 2025年乡镇土地租赁合同范本
- 快递柜安装协议书
- 2025年真空抽滤桶项目市场调查研究报告
- 陕西省特种设备隐患排查清单(2025年)
- 燃气公司加气站操作规程及安全要求
- 推进教育教学改革的实施路径
- 装修砸墙安全协议书
- 电力建设火力发电工程智慧工地技术规范
评论
0/150
提交评论