VC聊天程序设计步骤

上传人:d**** 文档编号:184023974 上传时间:2023-02-01 格式:DOCX 页数:17 大小:304.27KB
返回 下载 相关 举报
VC聊天程序设计步骤_第1页
第1页 / 共17页
VC聊天程序设计步骤_第2页
第2页 / 共17页
VC聊天程序设计步骤_第3页
第3页 / 共17页
点击查看更多>>
资源描述
实验4聊天程序【实验目的】熟悉VisualC+的基本操作。基本了解基于对话框的windows应用程序的编写过程。对于Windows Socket编程建立初步概念。【实验要求】 应用Visual C+中MFC CSocket类,实现网络数据传输。仿照本实验步骤,制作实用的局域网一对一聊天程序。【实验原理】一、Windows Socket和套接口的基本概念网际协议(Internet Protocol,IP)是一种用于互联网的网络协议,已广为 人知。它可广泛用于大多数计算机操作系统上,也可用于大多数局域网LAN(比 如办公室小型网络)和广域网WAN (比如说互联网)。从它的设计看来,IP是 一个无连接的协议,并不能保证数据投递万无一失。两个上层协议(TCP和UDP) 依赖IP协议进行数据通信。如果希望在Microsoft Windows下通过TCP和UDP协议建立网络应用程 序,则需要使用Winsock套接口编程技术。套接口,就是一个指向传输提供者的句柄。Win32中,套接口不同于文件描 述符,所以它是一个独立的类型SOCKETo Windows Sockets描述定义了一 个Microsoft Windows的网络编程界面,它是从Unix Socket的基础上发展而来 的,为 Windows TCP/IP提供了一个BSD型的套接字规范,除与4.3BSD Unix Sockets完全兼容外,还包括一个扩充文件,通过一组附加的A PI实现Windows 式(即事件驱动)的编程风格;而Winsock则是在Microsoft Windows中进行网络 应用程序设计的接口。Windows在Internet支配域中的TCP/IP协议定义了 Winsock网络编程规范,融入了许多新特点。使用Socket的目的是使用户在网络 协议上工作而不必对该网络协议有非常深入的了解。此外,编写的程序还可被迅 速地移植到任何支持Socket的网络系统中去。Winsock提供了一种可为指定传输协议打开、计算和关闭会话的能力。在 Windows下,TCP/IP上层模型在很大程度上与用户的Winsock应用有关;换言 之,用户的Winsock应用控制了会话的方方面面,必要时,还会根据程序的需要 格式化数据。套接口有三种类型:流式套接口、数据报套接口及原始套接口。流式套接口定义了一种可靠的面向连接的服务(利用TCP协议),实现了无 差错无重复的顺序数据传输。数据报套接口定义了一种无连接的服务(UDP协 议),数据通过相互独立的报文进行传输,是无序的,并且不保证可靠和无差错。 原始套接口允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议实 现的测试等。面向连接服务器处理的请求往往比较复杂,不是一来一去的请求应答所能解 决的,而且往往是并发服务器。使用面向连接的套接口编程,可以通过图1.1来 表示。nnL用图1.2表示。答就完成了客户 程序的流程可以套接口工作过程如下:服务器首先启动,通过调用socket()建立一个套接口, 然后调用bind()将该套接口和本地网络地址联系在一起,再调用listen()使套接口 做好侦听的准备,并规定它的请求队列的长度,之后,调用accept()来接收连接。 客户在建立套接口后就可调用connect()和服务器建立连接。连接一旦建立,客户 机和服务器之间就可以通过调用read()和 write()来发送和接收数据。最后,待数 据传送结束后,双方调用close()关闭套接口。在网络编程中,掌握端口的概念十分重要。端口 :基于TCP/IP协议的网络 中,计算机都分配有一个IP地址,用一个32位二进制数来表示,正式的称呼是 “Ipv4地址”。客户机需要通过TCP或UDP和服务器通信时,必须指定服务器 的IP地址和服务端口号。另外,服务器打算侦听接入客户机请求时,也必须指 定图1.2 一个IP地址和一个端口号。在选择端口时,应特别小心,因为有些可 用端口号是为“已知的”(即固定的)服务保留的,如文件传输协议和超文本传 输协议,即FTP(21号端口)和HTTP (一般为8080端口)。“已知的协议”,即 固定协议,采用的端口由“互联网编号分配认证(IANA)”控制和分配,RFC1700 中说明的编号。从本质上说,端口号可分成3类:“已知”端口、已注册端口、动态和(或) 私用端口。“已知”端口 01023,由IANA控制,是在UNIX中为固定服务保留的。已注册的端口 102449151,由IANA列出来的,供普通用户的普通用户 进程或程序使用。 动态和(或)私用端口 4915265535。普通用户应用应选择102449151 之间的已注册端口,从而避免端口号已被另一个应用或系统服务所用。此外,4915265535间的端口可自由使用,因为IANA这些端口上没有注册服务。图1-5二、MFC对Socket编程的封装类简介 Microsoft Windows Class Library(MFC)中提供了较高级封装的类用来实现网络通信。图1.3给出了 Csocket类的继承关系。CAsyncSocket类封装了 WindowsSockets API函数,提供了较低层的与 Windows Sockets对话接口,一般适合于有相当水平的网络编程者使用,可方便 地进行底层的网络事件通知及信息回叫控制等操作。CSocket类派生于CAsyncSocket,它继承了父类中一些常用易懂的Windows Sockets API函数,并对CAsyncSocket中底层的较难控制的一些API函数或成员 函数进行了处理,使得网络传输简捷易用,同时它支持模块化的后台信息处理, 解决了 CAsyncSocket中较难克服的多线程处理。下面介绍用VisualC+在 Windows中实现Socket的CSocket类型成员函数 (这些成员函数实际上是从CAsyncSocket类继承来的)。成员函数和参数说明:(l)BOOL Create(UINT nSocketPort=0,int nSocketType =SOCK_STREAM,long lEvent=FD_READIFD_WRITEIFD_OOBIFD_ACCEPTIFD _CONECTIFD_CLOSE,LPCTSTR lpszSocketAddress=NULL)该函数用来建立Socket,如果函数成功,则返回非零值;否则返回值为0。 其中:nSocketPort:为所选择的Socket端口,一般要大于1023,如果该参数为0, 则由系统选定一端口,默认值为0。nSocketType:为套接字类型SOCK_STREAM 或 SOCK_DGRAM。SOCK_STREAM表示为流套接字(本实验使用基于TCP连接的流套接字编程), SOCK_DGRAM表示为数据报套接字(将在以后实验中讲述),默认值为 SOCK_STREAM。lEvent :标识该Socket要完成哪种工作,默认值为 fd_readifd_writeifd_oobifd_acceptifd_connectifd_close。lpszSockAddress: 一个指向字符串的指针,该字符串包含了被连接套接口的 网络地址。一个带点的数字,如“128.56.22.8”,默认值为NULL。注意:CSocket中,Winsock API的初始化(socket)和绑定(bind)两部分工作都 完成了。(2)BOOL Listen (int nConnectionBacklog=5)该函数的作用是等待Socket请求,如果调用成功,则返回非零值;否则返 回值为0。Listen仅对那些支持连接的套接字起作用,也就是SOCK_STREAM 类型的套接字。在进程应答连接并把它放到等待队列时,套接字被置成被动模式 (passive mode)。本函数一般由哪些一次可以有多个连接的服务器使用(或任何 需要接收连接的应用)。nConnectionBacklog:表示等待队列的长度,默认值为最大值5,有效值为 15。 BOOL Connect(LPCTSTR lpszHostAddress,UINT nHostPort)该函数的作用是提出连接请求。其中:lpszHostAddress :对象连接的套接字的网络地址、机器名,如, 或以句点分隔的数字,如“ 211.80.43.100”。nHostPort :为接受请求进程的网络地址和Socket端口号。注意:Connect 函数还有另一个版本: BOOL Connect(const SOCKADDR *lpSockAddr,intnSockAddrLen);具体用法可以参阅 MSDN Library 中关于 CAnyscSocket 类的阐述。(4)virtual void Close()该函数的作用是关闭该Socket。三、利用CSocket进行传输的辅助类简介1.CSocketFile 类CSocketFile继承了 CFile类,见图1.4,它可以很自如地用来在基于Windows Socket网络上传输数据。首先,将一个建立连接CSocket对象实例作为参数进行 初始化,然后,将已经初始化的CSocketFile对象连接到CArchive对象上,接着 将数据串行化,以使用MFC系列来简化发送和接收数据,最终实现利用网络的 Socket传输和本机上的流传输一样简单。成员函数:CSocketFile用到的成员函数只有构造函数。CSocketFile:CSocketFile(CSocket*pSocket,BOOLbArchiveCompatible=TRUE );其中:pSocket:连接到CSocketFile对象的套接口。bArchiveCompatible:指示该文件对象是否与一个CArchive对象一起使用。只有当希望在单机方式下来使用这个CSocketFile对象时,才传递FALSE。 因为仅有CSocketFile类实例本身并没有什么意义,所以通常将其置为TRUE。说明:此成员函数用来构造一个CSocketFile对象。当此对象超出范围或被 删除时,它的析构函数将使它自己从插槽对象上分离。注意:一个CSocketFile对象也可以在没有CArchive对象的情况下作为一个 (受限制的)文件来使用。缺省情况下,CSocketFile构造函数的 bArchiveCompatible参数是TRUE,它表明此文件对象是与一个档案一起使用的。 要在没有档案的情况下使用该文件对象,则给bArchiveCompatible参数传递 FALSE。在“档案兼容”模式下,一个CSocketFile对象可以提供更好的表现, 并减少出现“死锁”的几率。CSMkctFlleI?理 n二图1.42. CArchive 类CArchive类没有基类。CArchive允许以一个永久二进制(通常为磁盘存储) 的形式保存一个对象的复杂网络,它可以从永久存储中装载对象,并在内存中重 新构造它们。使数据永久保留的过程就叫作“串行化”。一般可以把一个CArchive 对象看作一个二进制流,可以将它和输入输出流iostream类的用法进行比较。 CArchive对象一般和一个文件类关联(CFile类或CSocketFile类)。输入输出流 是加工处理ASCII字符,而CArchive类的用处是高效、无冗余地处理二进制数 据。在CArchive类中,重载了提取()和插入()运算符,它是方便的归 档编程接口,主要支持CObject派生类。四、MFCCSocket类的通信流程使用CSocket类进行网络二进制数据通信的连接流程,如下表所示。1构询一个叫匕封技clkait;i6(jJcirO:Mt JCkielm d loi Lc R.7Jk. 6oJdrtJ;听W与阍务贸it cl loi Lc.DDicL01nddrr njicirO:此叫阴狷,箸籽服务嚣舄初听.1ISaJoetn reoeire;i jerverLMCQ叩 L h nsxrm):It封朋寤-等特客户用段孩.构询新的 心肮时孩剧以接世客户够的歧孩ibCikfen serve。;构避一玄怀时#Cbferi_jt!n-e!n);7 A rJijrii t Ckr CA nJii就:加d):7 A rJijrxjulfi Qk. ( A r:i ire3 rdi海firii nkr CAmlik-eizhud);CA Th*urjuL Hkr C A kJi Lw二如Z;jrii Azjkie;用流进廿数葬的网折断g和 cilr cxiut.H| 似iirh;uRjutCralue:注意事项:利用CArchive类进行网络数据传输的操作固然方便直观,但是 如果编写的程序是和别人的程序进行通信的话,就要注意对方的程序是否也用了 CArchive类,否则会造成数据相互不能识别。五、使用CSocket类的同步问题和解决方法有了以上的基础,就可动手进行网络数据通信了,可以做到基于阻塞发送和 接收二进制数据。比如,可以Client端发送,Server端接收:Server 端:m_receive.Receive(void*lpBuf,intnBufLen,intnFlags= 0);Client 端: m_client.Send(constvoid*lpBuf,intnBufLen, intnFlags=0);接着,再分析一下各个类中提到的常用方法的同步特性:Listen(.):执行后不管有没有连接,立即返回。Connect。.):如果服务器端有端口正在侦听,则立即成功返回;如果没有, 则过几秒钟将显示无法连接。Accept(.): Listen函数返回后可以执行此函数,但是此函数是基于阻塞的, 只要客户机connect连接并且端口正确,则立即成功返回,建立连接;如果迟迟 侦测不到连接,则不断阻塞,直到连接成功或者强行关闭。Send(.):调用后就将数据保存在socket缓冲区中,立即返回。Receive(.):和Accept 一样的阻塞,直到能从socket缓冲区成功读取到 nBufLen长度的数据。按上分析,读者可能会想到这样两个问题:在侦听的时候,如果客户端迟迟没有连接,则侦听方执行到Accept则阻 塞不能响应。在用Receive接收数据,如果迟迟得不到发送的数据,也阻塞不能响应。显然,带有这两个问题的软件是不能接受的。幸亏CSocket类里可以使用 继承自CAsyncSocket里的OnReceive和OnAccept消息处理函数,其原理分别是:(1) OnAccept(): Listen过后,如果侦测到客户机有连接,则产生消息调用 OnAccept(),一般可以在此函数里面调用Accept便可避免侦听时的阻塞。Virtual void OnAccept(intnErrorCode)其中:nErrorCode :套接字上最近的错误代码。此成员函数可用的错误代码有:0:函数成功地执行并返回;WSAENETDOWN: Windows Sockets检测到网络系统故障。说明由框架调 用,通知监听套接字现在可以调用Accept成员函数来接收挂起的连接请求(有 connect请求进入)。(2) OnReceive():建立连接后,如果侦测到Socket缓冲区里有数据到达,便 自动调用OnReceive(),在此函数里面使用Receive接收就可避免接收数据的阻 塞。Virtual void OnReceive(intnErrorCode);其中:nErrorCode :套接字上最近的错误代码。此成员函数可用的错误代码有:0:函数成功地执行并返回;WSAENETDOWN : Windows Sockets检测到了网络故障。说明本函数由框 架调用,通知套接字缓冲中有数据,可以调用Receive成员函数取出。【实验步骤】下面以一个最简单的点对点通信的聊天程序为例:客户机/服 务器模式是socket点对点网络程序典型的模式。它用到的方法也是面向连接TCP 连接的套接字MFC典型方式。其工作过程是:服务器首先启动,创建套接字后 等待客户的连接;客户启动以后,创建套接字,然后和服务器建立连接;连接建 立后,客户机和服务器可以通过建立的套接字连接进行信息通信。先建立一个MFC,选dialogBased,工程名为LX2,如图1.5所示。图1.5下一个对话框选择W indow Sockets,后面的选项酌情考虑,或者连续选择 默认的即可,如图1.6所示。上1功writer顷 DEHtlnnP IfflndmFnr Swkcli-救:如果忘了添加W indows Sockets选项,可以在文件头部添加下列语句进行补# include W insock.h# include Ws2tcpip.h# pragma comment(lib, W s2_32.lib)注:这些语句支持winsock2。出现Dialog以后,编辑界面,使其如图1.7所示并且对控件点击右键,选 择属性选项,把每个控件的ID改掉(控件ID就是每个控件的名字,要改成有意 义的,以便将来管理)。各个控件的ID如下表,并且在对话框视图中点击右键,选择ClassWizard 选项,用该工具对控件添加变量,使其如图1.8所示。排定变lit类梨甜向并间|的并忤HlC_CUnTtNTii. _ri 实CblTEIJi始无吸逆内容的玄巾机HlC_CUnTtNTCt:始无吸逆内容的玄巾机mC_l.UFENn. _ JisfamiCHuttcmJDC_yENDn_!t5idCHuttoiiMH dwiMTriinj接着,再打开一个VC,建立客户机工程,工程名称为LX1,各个控件的ID 如下表,界面如图1.9所示。交*排定变代类里时向界面1:的并作JDC_CONJENTri. _ri.熨r % 的Ljdc_conjentn_ctrlC愉区发送肉容的玄市第jdc_conni:cj11. _CUIIIItK:l!.C H ultai蛔B按期jDt_a:NDri. _stsidC H ultai筮送网1的M接1的T的玄本郦.2tn UJ 7快Align ftcH -r n 基 gted.CMrCi.r _9EMfonvrn甘 *anl rlwn jV BiinrF UeM r iwgO末尼添加语句.使JC如卜,所示: m,ndnabfeW inde FALSE):,。使发送按徂戋矢 ream TRUE;/tewni TRUE unless you/set ihe focu s ra controlm诟个滑句作用使发攻按徂失角以免炬未姓 接用户就点品发送,发生不叩预计的错误.为了在中更11由地处理CSocket ?J到的消息, 必须新it CSocket的派与类:在Lx2工程的工作区类祝图中(图1.10点由石槌, 添加新类,CSeiver 父类为 CSocket .NewChss对话柞如图1.11所示.IV 1.11在ixZDlgJi斗!添加:大文 fhinc hide *Seneihpt ivate CSetverm. st rvt t:( Setvata(TRl*E):m _recv.Send tri in :. -1.in cuLSetSel. -1);m_ctri.ReplaceSeir.TRl E);将发日框IM地,在Lxl l:m图中点由右建,添加浙共:Cclient它继承 1*1 CSccket. (v CLxlD lg 类 添加 private 安 lit:CC lientm client:双击对话框图像匕的.,连接”按钮.添加代仰:void CLxlD Ui:OnConnectOUpdate ata (TRIE);m_clientCreale(100l);/ 使用 1001H1n_clientjCnnect(n_ip. 1000)连接 11 标地灿.1000 11A IkM essaiseBooc fC Ibn t W; il 接成功勺: m_send.EnableW indjh pM aiiW nd)-ShcwA cceptO;/这里仅仪添加了这-句,因为CLx2Dfe类是发送接收消息的主窗口,H此旦应用程序发送接收的消息也在CLx2Dlg对象实例中进行,/所以当CSeiver类的对象收到客户机的Connect消息时,/便可调用CLx2D也对象中的ShcwAcceptO函数处理-I CIM-; Wi-Illi IINII 照IIH -ill11)1I|)I :iJraCitHk0 flMag pPfOraOutSFBandDala 0nRniw4 Dn钮TMpiiihnr iwunnr.v irtculvi;IJrni-|O1-CJIl JUUy :nl| Avpl国 J.12该步完成以扁 可以为cLx2Dfe类添加pubhe成员函数ShcwAcceptQ tvoid C Lx2D g:Show A ceeptm serve eA ccept(ii recv);A &M cssa第BoxfScivcr 端连接成功);m.send.EnabkW ridow (TRL h);才连接成功,M以发送m listen.E nabkW indow LSD;同时禁止侦听按钮是,当客户机调用 nt clmtCcnnect(n_i)( 1000);时,K机 server端发现并调用ShowAeccpL 函数来建立连接。执行完以后,Socket连接便被建立。接下来的工作便是添加发送聊天信-息的函数丁。注意我物面点击发送按钮的OnSendO函数己经添加好了,在Lx2 I.程中只要添加iv我 端的接收消息和显示消息功能就可以进行消息的传送在CSaver类中像添加OnAcceptjj ,-样添加成员函数0nRoccc0 :void C S civer :O nR occivcditnH iidiC ode)/T0D0 :Add yourspcchlidcd code here and/orcaUthe base ebss C SockcL:Or R ccc ive .iL pM ahW nd)-ShawM sgO;建立连接后,-方 -IL发送数据,另-方的CSocket派生类便调用该函数。其中代码叮以参 考前面0 nA 口ceptO进行理解-在CLx2D电里添加成员函数ShowM sgO :void CLx2DIgWhowM sg。char buflSSS;接收消息到tmf里面,长度255字节十用AMessacBox函数显示接收到的字符串这里注意CStrr类的用法hl recv.R eeeivetiufi 255);C Strrigm sg;m sg.Fcitm atC% liud);A IxM cssagcBoxi sg);同样地,逐步在Lxl I:程中添加消息接收函数: void CClientD nReeeive (hintrmiode)/ T 0 D 0 :Add yoursfjochlizcd code here and/or call the base ebss(CLxlDl)lxGolAppG-.iL pM ahW nd)-ShowM 第O;C SockcLOn R oco ive hE mtC odo);void CLxlDlg:ShcwM sgOchar buf255;m clfenLReceivetju 255);以接收消息到huf里面,长度2SS字节C Strrigm sg;ms.Fcitm atC% sA, liul);A ftil essageBoxii ;用A ftM龄sa知Box函数显示接收到的字符出最后的收尾工作不要忘记,即在对话框销毁的时候,关闭Socket连接,释放资后。以下 以成1工程为例,见图1.13.-TEf .用找二停网7|L2T.4.i.LBffjr【思考题】改造程序结构。上面的程序能做到双向发送消息,但是两个程 序必须成对使用,即一个是Server端,一个是Client端;而真正实用的聊天程序 即使使用了 Client/Server模式,也必须将其整合,使其所有的功能都在一个程序 中实现,以增加适用性。试改造结构,将两个程序的功能整合在一起。界面参见 。添加程序功能。以下几点可供参考:用AfxMessageBox()显示消息显得不够专业,可以考虑制作一个双文本 框的界面,让发送的消息在下面一个文本框中输入,接收的消息在上面的文本框 中显示。可考虑在显示的文本框中添加滚动条让消息具有往下滚动的功能。增加保存聊天记录的功能。界面可参考图1.15。为简化操作,本实验直接利用了 CSocket类的Send和Receive进行通信。 请参照实验原理部分的CSocketFile类和CArchive类的说明以及通信的流程图对 其进行改造,以便更方便、高效地进行大量的数据交换。
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 图纸设计 > 毕设全套


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!