聊天室程序设计报告
实验5 5 掌握简单的网络通讯技术 实验6 掌握基于典型协议的的网络通讯技术 一一 实验目的实验目的 1.熟悉Socket 的通讯机制,了解网络程序的设计方法。 2. 熟悉典型协议的通讯机制,掌握基于它们的网络系统设计方法。如TCP、UDP。 二二 实验环境实验环境 1.Windows7 2.Visual C++ 6.0 三三 实验程序设计实验程序设计 1.1.实验原理实验原理 1.C/S模式 C/S模式是指一个服务器同时为多个客户端服务。 并发性是C/S模式的的基础, 正是由于 并发性的支持, 多个客户端能够获得同一种服务, 而不必等待服务器完成对上一个请求的处 理。 在C/S模式中,当请求到达服务器时,服务器将它交给一个控制线程,它能与已有的线 程并发的执行。 在设计并发服务器时, 一般服务器代码由两部分组成, 第一部分代码负责监听并接收客 户端的请求, 还负责为客户端请求创建新的服务线程; 另一部分代码负责处理单个客户机请 求,如与客户机交换数据,提供具体服务。 下图所示为服务器创建多个线程来为多个客户机服务。 2.基于TCP的socket通信 服务器与客户端是通过套接字来进行通信的。 在基于TCP的网络通信程序中,首先服务器端通过socket()函数创建套接字,然后通过 bind()函数来命名套接字, 调用listen()函数开启服务器端的监听。 接着执行accept()函数 来接收客户的连接,服务器阻塞等待客户连接请求,直到有客户请求连接。 客户端创建套接字,接着通过connect()函数请求连接服务器,连接成功后,就可以与 服务器进行通信了。 服务器与客户机通过send()各recv()调用来进行信息的发送和接收。 只有当有信息可接 收时,recv()才返回,否则将阻塞。 通信完后,服务器和客户机各自通过closesocket()函数来关闭套接字。 注:以上讲的是阻塞模式。 下图所示的是基于TCP的网络通信模式。 服服 务务 器器 端端 客客 户户 机机 端端对 于 监 听 套 接 字 创 建 套 接 字 : SOCKET() 对 于 连 接 套 接 字 绑 定 套 接 字 ;BIND() 创 建 套 接 字 : SOCKET() 启 动 监 听 : LISTEN() 请 求 连 接 : CONNECT() 请 求 连 接 ( 第 一 次 握 手 ) 接 受 连 接 ( 第 二 次 握 手 ) 接 受 客 户 的 连 接 请 求 : ACCEPT() 创 建 新 的 连 接 套 接 字 如 果 没 有 已 经 到 达 的 连 接 请 求 , 就 阻 塞 , 等 待 客 户 的 连 接 请 求 发 送 数 据 : WRITE() 请 求 服 务 器 服 务 ( 第 三 次 握 手 , 同 时 发 送 数 据 ) 处 理 服 务 器 的 响 应 服 务 器 发 给 客 户 机 的 响 应 读 取 数 据 : READ() 发 送 数 据 : WRITE() 处 理 客 户 机 的 服 务 请 求 读 取 数 据 : READ() 关 闭 套 接 字 : CLOSE() 关 闭 套 接 字 : CLOSE() 关 闭 套 接 字 : CLOSE() 2. 2.系统设计系统设计 实验5要求在客户机和服务器传输图片和文件,如果是图片则显示,是文件则保存。这 个实验中的客户机与服务器可以没有区别, 即可以采用对等的模式, 双方既可以是服务器也 可以是客户机。因为没有要求一个对多个服务。 实现实验5中的要求最简单的可以选用基于UDP的对等模式,但是我们小组决定将实验5 和实验6的功能集成在一个程序中, 所以最后还是选用了基于TPC的网络通信。 由客户机发送 文件或图片到服务器, 服务器检测到有文件可接收时, 提示用户是否要接收来自己客户机的 文件或图片,如果接收,则根据文件后缀名来判断文件类型,是图片就打开。 实验5中,难点在于怎么传递和接收文件,怎么判断一个文件是否传或者接收成功了。 在传文件的过程中,我们先组装数据包,在数据包中,我们先传文件标识符,文件标识符是 为了和聊天时的消息标识符以及其他自定义的标识符区分接收。 然后再传文件名和文件的大 小,最后是文件的内容。服务器接收时,依次解析出文件标识,文件名,文件大小,文件内 容。 图片也是文件,通过后缀名可以识别是图片还是非图片。 实验6要求编写一个多人聊天室系统。聊天室程序是一个服务器接收来个多个客户端服 务请求,这些请求是并发。采用C/S模式设计,服务器开启一个监听线程来接受来自一个客 户端的连接请求,在收到请求后,在这个线程中为这个客户提供交互服务, 同时开启另一个 监听线程来监听其他客户的连接请求。 这样就实现了服务器为多个不同的客户端提供并发服 务。 在设计C/S模式,当客户端很多时,或者并发很大时,阻塞模式是行不通的,因为可能 造成多个客户机同时争夺服务器时, 有的客户机不能及时得到服务而影响用户体验。 我们小 组曾尝试采用非阻塞模式, 用了Select模型。但是由于以前没有网络编程经验、 时间有限以 及非阻塞模式很复杂,没有成功实现,最后还是采用了阻塞模式。不过,在实验中,还是没 有出现性能问题。 怎么实现多人聊天室通信?首先客户机发送聊天信息到服务器, 服务器接收到聊天信息 后,在服务器的显示信息,并转发给所有的其他客户机。 服务器可以发送公告信息给所有的 客户机。当客户机下线时,该客户机发送下线标识消息到服务器, 由服务器广播到其他客户 机。 设计了一个在线客户列表, 来同步时实显示在线的客户。 实验中一个要点在于怎么实现 同步显示在线客户。下面将在系统实现中讲述。 3.3.系统实现系统实现 这部分主要结合关键代码来讲解系统的实现思路及具体实现, 详细代码见附录。 我们小 组实验5和实验6是在一个程序中实现的。 (1)服务器与客户端通信 服务器开启监听,这部分主要实现创建套接字、命名套接字、 套接字监听,然后开启一 个监听线程。 m_serversock=socket(AF_INET,SOCK_STREAM,0);//创建 ret=bind(m_serversock,(LPSOCKADDR)//绑定 ret=listen(m_serversock,10);//监听 AfxBeginThread(ListenThread,this);//开启一个监听线程 在ListenThread线程中, 接收客户端请求, 接收阻塞解除后再开启另一个监听线程来监听其 他客户机的连接请求。 Clientsock[k].clientsock=accept(pDlg-m_serversock,(sockaddr *)//接收客户端请求 AfxBeginThread(ListenThread,p); //开启另外一个监听线程,监听其他用户连接 接下来,接收信息标识符,并根据不同的消息标识符来判断采用相应的处理函数。char recvflag[3]; memset(recvflag,0,3); int flagc=recv(clientsock[k].clientsock,recvflag,2,0); recvflag[2]= \0 ; CSt