VC网络聊天软件课程设计报告书_第1页
VC网络聊天软件课程设计报告书_第2页
VC网络聊天软件课程设计报告书_第3页
VC网络聊天软件课程设计报告书_第4页
VC网络聊天软件课程设计报告书_第5页
已阅读5页,还剩63页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、. . . . 1 / 68摘摘 要要网络聊天室,其实质就是基于 Internet 的一种网络聊天软件。它可以在网络环境下进行实时的一对多或多对多的匿名交谈。网络聊天室软件的制作方法有很多种,比如用 MFC 和 Java 等语言设计的就有很多,本次课程设计主要是利用 MFC 所提供的各种控件尤其是 WinSock 控件,基于 C/S 模式,设计了一个网络聊天室,圆满地实现在网络上实时聊天与多种人性化的辅助功能。关键词:WinSockWinSock;C/SC/S ;VisualVisual C+C+ 6.06.0;聊天室聊天室. . . . 2 / 68目录目录.查找资料 41.1 网络聊天程序

2、的开发背景 41.2 网络聊天程序的设计目标 4.相关知识 52.1 WINSOCK介绍 52.2MFC 的 CASYNCSOCKET类和 CSOCKET类 62.3 利用 CSOCKET进行有连接的通信 82.4 方案比较与选择 9.详细设计 .14.1 聊天程序现 .15.程序流程图 624.1 建立连接的流程图 624.2 客户关闭或者注销时的程序流程图 63.程序运行结果 645.1 客户端 645.2 服务端 64、讨论与进一步研究建议 65、课程设计心得 66、参考文献 67. . . . 3 / 681.查找资料当前是数字信息时代,网络时代,获得信息的渠道做种多样。而最为快速的当

3、然就是网络了。所以在课程设计动员之后,我们就马不停蹄的通过互联网收缩有关网络编程和 MFC 编程的有关资料。找到大量资料之后,我们还有根据课程设计的要求进行筛选资料,最后选定方案和确定实现方法。这也是我们第一阶段的工作。 1.1 网络聊天程序的开发背景近年来,互连网发展日新月异,网络使空间的距离不再成为人们沟通的障碍,世界各个角落的人们可以通过 Internet 收发、实时聊天、获取最新的资讯。所以网络聊天的程序早已被前人所实现,而且实现的方法多种多样。因此,本次课程设计,我们主要借鉴前人创立的方法和编程经验来制作一个 C/S 聊天室程序,通过制作该程序达到的学习网络 socket 编程和使用

4、 MFC 编程的相关知识。 1.2 网络聊天程序的设计目标本课题是设计一个网络聊天的程序,包括服务器端和客户端,主要功能为: 客户端部分:、输入服务器端 IP 地址和端口号进行连接、发送消息给服务器端并显示服务器端回传的消息、在客户端增加历史聊天记录和当天聊天记录、可以设置个性昵称、增添快捷表情、更换个性图像和背景设计服务器端部分:、立服务器端与客户端的连接请求. . . . 4 / 68、接收所有用户发送的消息、向所有在线用户群发消息、在客户端增加历史聊天记录和当天聊天记录、可以设置个性昵称、增添快捷表情、更换个性图像和背景设计通过这次课程设计,可以比较深入的了解和掌握 WINSOCK 控件

5、基本属性、方法和事件,熟悉 VC+的开发环境。理解网络聊天通信的概念,输控制协议(TCP)进行数据交流,初步掌握网络聊天通信程序的设计方法,以与 WINDOWS编程的一些方法。并能巩固和扩展之前学过的知识,进行项目的设计开发训练,更好的适应社会的需求。 . . . . 5 / 682.相关知识2.1 Winsock 介绍Windows Sockets 规以 U.C. Berkeley 大学 BSD UNIX 中流行的 Socket 接口为例定义了一套 Micosoft Windows 下网络编程接口。它不仅包含了人们所熟悉的 Berkeley Socket 风格的库函数;也包含了一组针对 Wi

6、ndows 的扩展库函数,以使程序员能充分地利用 Windows 消息驱动机制进行编程。 Windows Sockets 规本意在于提供给应用程序开发者一套简单的 API,并让各家网络软件供应商共同遵守。此外,在一个特定版本 Windows 的基础上,Windows Sockets 也定义了一个二进制接口(ABI) ,以此来保证应用 Windows Sockets API 的应用程序能够在任何网络软件供应商的符合 Windows Sockets协议的实现上工作。因此这份规定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。 遵守这套 Windows Socket

7、s 规的网络软件,我们称之为 Windows Sockets兼容的,而 Windows Sockets 兼容实现的提供者,我们称之为 Windows Sockets 提供者。一个网络软件供应商必须百分之百地实现 Windows Sockets规才能做到现 Windows Sockets 兼容。 任何能够与 Windows Sockets 兼容实现协同工作的应用程序就被认为是具有 Windows Sockets 接口。我们称这种应用程序为 Windows Sockets 应用程序。 Windows Sockets 规定义并记录了如何使用 API 与 Internet 协议族(IPS,通常我们指的

8、是 TCP/IP)连接,尤其要指出的是所有的 Windows Sockets 实现都支持流套接口和数据报套接口. . . . 6 / 68 应用程序调用 Windows Sockets 的 API 实现相互之间的通讯。Windows Sockets 又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。 2.22.2 MFCMFC 的的 CAsyncsocketCAsyncsocket 类和类和 CSocketCSocket 类类构造一个 CAsyncSocket 对象并使用该对象创建基础 SOCKET 句柄。 套接字的创建:遵循两阶段构造的 MFC 模式。 例如: CAsyncSoc

9、ket sock;sock.Create( ); / Use the default parameters - 或 - CAsyncSocket* pSocket = new CAsyncSocket;int nPort = 27;pSocket- Create( nPort, SOCK_DGRAM ); 上面的第一个构造函数在堆栈上创建一个 CAsyncSocket 对象,第二个构造函数在堆上创建 CAsyncSocket 。上面的第一个 Create 调用使用默认参数创建流式套接字,第二个 Create 调用创建具有指定端口和地址的数据文报套接字。 (任一个 Create 版本都可以和任一

10、种构造方法一起使用。 ) Create 的参数有: “端口”:短整型。 对于服务器套接字,必须指定端口。对于客户端套接字,通常接受此参数的默认值,该值允许 Windows Sockets 选择端口。 套接字类型: SOCK_STREAM (默认值)或 SOCK_DGRAM 。 套接字“地址” ,如“”或“128.56.22.8” 。 该地址为网络上的网际协议 (IP) 地址。很可能要始终依赖此参数的默认值。 如果套接字是客户端,则使用 CAsyncSocket:Connect 将此套接字对象连接到服务器套接字。 如果套接字是服务器,则将套接字设置为开始侦听(使用 CAsyncSocket:Li

11、sten)来自客户端的连接尝试。接收到连接请求时,. . . . 7 / 68用 CAsyncSocket:Accept 接受该请求。 接受连接后,可以执行验证密码等任务。注意 Accept 成员函数采用对新的空 CSocket 对象的引用作为它的参数。在调用 Accept 之前,必须构造该对象。如果此套接字对象超出围,则连接关闭。不要对这个新套接字对象调用 Create 。 通过调用 CAsyncSocket 对象的封装 Windows Sockets API 函数的成员函数,与其他套接字进行通信。 如果在堆栈上创建了套接字对象,当包含函数超出围时将调用此对象的析构函数。如果使用 new 运

12、算符在堆上创建了套接字对象,则您必须负责使用 delete 运算符销毁此对象。 析构函数在销毁对象之前调用对象的 Close 成员函数。. . . . 8 / 682.3 利用 CSocket 进行有连接的通信微软的 MFC 把复杂的 WinSock API 函数封装到类里,这使得编写网络应用程序更容易。CAsyncSocket 类逐个封装了 WinSock API,为高级网络程序员 提供了更加有力而灵活的方法。这个类基于程序员了解网络通讯的假设,目的是为了在 MFC 中使用 WinSock,程序员有责任处理诸如阻塞、字节顺序和在Unicode 与 MBCS 间转换字符的任务。为了给程序员提供

13、更方便的接口以自动处理这些任务,MFC 给出 了CSocket 类,这个类是由 CAsyncSocket 类继承下来的,它提供了比CAsyncSocket 更高层的 WinSock API 接口。CSocket 类和 CSocketFile 类可以与 CArchive 类一起合作来管理发送和接收的数据,这使管理数据收发更加便利。CSocket 对象提供阻塞模式,这对于 CArchive 的同步操作是至关重要的。阻塞函数(如 Receive()、Send()、ReceiveFrom()、SendTo() 和 Accept())直到操作完成后才返回控制权。因此如果需要低层控制和高效率,就使用 Ca

14、syncSock 类;如果需要方便,则可使用 CSocket 类。由于我们对网络底层的了解比较浅薄,所以这次课程设计我们选择了采用CSocket 类来编程实现。下面主要针对这种方法进行讲述。使用 CSocket 对象涉与 CArchive 和 CSocketFile 类对象。以下介绍的针对字节流型(即基于 TCP/IP 协议)套接字的操作步骤中,只有第 3 和第 4 步对于客户端和服务端操作是不同的,其他步骤都一样。 构造一个 CSocket 对象。 使用这个对象的 Create()成员函数产生一个 socket 对象。在客户端程序中,除非需要数据报套接字,Create()函数一般情况下应该使

15、用默认参数。而对于服务端程序,必须在调用 Create 时指定一个端口。需要注意的是,CArchive 类对象不能与数据报(UDP)套接字一起工作,因此对于数据报套接字,CAsyncSocket 和 CSocket 的使用方法是一样的。 如果是客户端套接字,则调用 CAsyncSocket Connect()函数与服务端套接字连接;如果是服务端套接字,则调用 CAsyncSocketListen()开始监听来自客户端的连接请求,收到连接请求后,调用CAsyncSocketAccept()函数接受请求,建立连接。请注意 Accept()成员函数需要一个新的并且为空的 CSocket 对象作为它的

16、参数。 重载 CSocket 类. . . . 9 / 68的部分函数。客户端需要重载 OnReceive(int i) 和 OnClose(int i);服务器端需要重载 OnAccept(int i) 、OnClose(int i) 和 OnReceive(int i); 调用 Send()的方法来发送数据,调用 Receive()的方法来接受数据。 调用Close()方法来关闭套接字以终止通信。通讯完毕后,销毁 CSocket 对象。2.42.4方案比较与选择方案比较与选择系统分析与设计系统分析与设计1、系统构架方式如下图所示:设计出一个完整的网络聊天程序,使之实现以上基本要求。1、 服

17、务端需要完成的三件事1) 在特定端口等待连接请求,并需要维护一个客户连接表,已记录所有成功连接。2) 与时接受消息,然后转发到客户连接。3) 监控连接状态,客户离开或故障时从列表中删除相应表项,并与时更新连接表。. . . . 10 / 682、 客户端需要完成的三件事1) 建立与维护服务器的连接,并随时监测连接状态。2) 把用户输入的信息与时发送到服务端,同时准备好接受,并显示信息。3) 在用户退出时关闭连接。程序方案程序方案比较:比较:方案一:基于方案一:基于 TCPTCP 的的 socketsocket 编程编程TCP(Transmission Control Protocol,传输控制

18、协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。服务器端程序流程如下:1) 创建套接字(socket) ;2) 将套接字绑定到一个本地地址和端口上(bind) ;3) 将套接字设为监听模式,准备接受客户请求(listen) ;4) 等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept) ;5) 用返回的套接字和客户端进行通信(send/recv) ;6) 返回,等待另一客户请求;7) 关闭套接字;客户端程序流程如下:1) 创建套接字(socket) ;2) 向服务器发出连接请求(connect) ;3) 和服务器端进行通信

19、(send/recv) ;4) 关闭套接字。在服务器端,当调用 accept 函数时,程序就会等待,等待客户调用connect 函数发出连接请求,然后服务器端接受该请求,于是双方就建立了连接。之后,服务器端和客户端就可以利用 send 和 recv 函数进行通信了。因为服务器需要接受客户端的请求,所以必须告诉本地主机它打算在哪个 IP 地址和. . . . 11 / 68哪个端口上等待客户要求,因此必须调用 bind 函数来实现这一功能。而对客户端来说,当它发起连接请求,服务器端接受请求后,在服务端就保存了改客户端的 IP 地址和端口的信息。这样,对服务器端来说,一旦建立连接之后,实际上它已经

20、保存了客户端的 IP 地址和端口号的信息,就可以利用所返回的套接字调用 send/recv 函数与客户端进行通信。程序流程图如下:方案二:基于方案二:基于 UDPUDP(面向无连接)的(面向无连接)的 socketsocket 程序程序UDP(User Data Protocol,用户数据报协议)是与 TCP 相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去。UDP 适用于一次只传送少量数据、对可靠性要求不高的应用环境服务器端也叫接收端,对于基于 UDP(面向无连接)的套接字编程来说,它的服务器端和客户端这种概念不是很强化,我们也可以把服务器端,即先启动的一端

21、称为接收端,发送数据的一端称为发送端,也称为客户端。服务端程序编写流程如下:. . . . 12 / 681) 创建套接字(socket) ;2) 将套接字绑定到一个本地地址和端口上(bind) ;3) 等待接受数据(recvfrom) ;4) 关闭套接字。虽然面向无连接的 socket 编程无须建立连接,但是为了完成这次通信,对于接受端来说,它必须先启动以接受客户端发送的数据,因此接收端必须告诉主机它是在哪个地址和端口上等待数据的到来,接收端(服务器端)必须调用bind 函数将套接字绑定到一个本地地址和端口上。客户端程序编写流程如下:1) 创建套接字(socket) ;2) 向服务器发送数据

22、(sengto) ;3) 关闭套接字。在 UDP 的套接字编程时,利用的是 sendto 和 recvfrom 这两个函数实现数据的发送和接收,而基于 TCP 的套接字编程时,发送数据是调用 send 函数,接受数据调用 recv 函数。程序流程图如下:. . . . 13 / 68方案比较结果方案比较结果TCP 与 UDP 最基本的区别在于基于连接与无连接,相比之下,第一种方案对系统的要求以与数据量都比较大,但是保证数据的正确性与数据顺序,在传输大量数据的时候具有更高的可靠性。至于第二种方案的优点在于传输的速度快,程序结构精简。总的来说,我认为 TCP 协议更能满足目前各行业对远程数据传输的

23、要求,它提供更稳定更便利的传输通道,满足了对安全性的要求以与远程数据传输的要求。所以我们小组选择方案一。. . . . 14 / 683.3.详细设计详细设计我们利用 MFC 提供的 CSocket 类来编程实现一个网络聊天室。那么就需要一个聊天的服务器(即是服务端) ,它可以和很多客户端进行通信,从而把来自不同的客户的聊天信息转交到所有其他的客户端。当然也需要用户界面(客户端) 。这样就形成了一个采用Client/Server 结构的并可以多人同时在线的聊天室。同时,服务器端应该有一定的管理功能,如手动/自动响应申请、设置服务器名称和服务器端口、在线统计、单独断开某人连接以与保持聊天记录等功

24、能。对于客户端,因为是面向用户,所以外观和功能都应有更高的要求。实现诸如:手动输入 IP 和用户名、头像切换、心情书写、表情输入、软件皮肤切换、注销登录、保存聊天记录以与伸缩界面等功能。下面详细介绍各项功能是如何实现的。3.13.1 聊天程序的实现聊天程序的实现(1)首先启动 Visual C+ 6.0,利用 MFC AppWizardEXE建立一个新的 MFC工程,工程名为 chat,在 MFC AppWizard Step1 的时候选择 Dialog based 即基于对话框,在 Step4 时勾选 Windows Sockets 选项(如图表 02) ,其他默认值下一步。. . . .

25、15 / 68图表 01图表 02(2)客户端的界面如图图表 03 所示。其中包含文档编辑框、按键控件、静态文本控件组成。左半边由上自下分别是:头像、昵称、当天聊天信息显示、12. . . . 16 / 68个表情按钮、消息输入框和发送按钮。右半边有历史记录显示框、历史记录显示按钮。图表 03 软件界面图表 04 控件类型与各自 ID标题控件类型控件 ID昵称:StaticIDC_STATIC服务器 IP:StaticIDC_STATIC端口号(默认 5000):StaticIDC_STATIC头像ButtonIDC_TouXiang表情 1ButtonIDC_BQ1表情 2ButtonIDC

26、_BQ2表情 3ButtonIDC_BQ3表情 4ButtonIDC_BQ4表情 5ButtonIDC_BQ5表情 6ButtonIDC_BQ6表情 7ButtonIDC_BQ7表情 8ButtonIDC_BQ8表情 9ButtonIDC_BQ9. . . . 17 / 68表情 10ButtonIDC_BQ10表情 11ButtonIDC_BQ11表情 12ButtonIDC_BQ12发送ButtonIDC_SEND连接ButtonIDC_CONNECT建立ButtonIDC_SETSERVER聊天纪录ButtonIDC_LiaoTianJiLu聊天信息显示EditIDC_SHOWTEXT信

27、息输入EditIDC_INPUTTEXT昵称输入EditIDC_NAME服务器 IP 输入EditIDC_SERVERIP端口输入EditIDC_PORT聊天记录显示EditIDC_ShowHistory聊天程序总共有 6 个类。其中,CChatApp 和 CAboutDlg 由 AppWizard 实现;另外,CServerSocket 和 CClientSocket 分别负责服务端和客户端的网络通信功能;CChatDlg 为程序的主控类,主界面、通信方式与程序逻辑均由该类实现,它继承自 CDialog 类;CMessgage 是对消息的封装。CClientSocketCClientSock

28、et通过相应的 OnReceive 消息来接收数据,响应 OnClose 消息来断开对话的处理,实现以 CArchive 对数据进行的串行化。类定义代码如下:#includeMessg.h /命令目标class CChatDlg;class CClientSocket:public CSocket. . . . 18 / 68public: CArchive *m_aSessionIn; CArchive *m_aSessionOut; CSocketFile *m_sfSocketFile; CChatDlg *m_dlg; bool m_bInit; /是否进行了初始化 bool m_bC

29、lose; /连接是否关闭public: void Init(CChatDlg *dlg); BOOL SendMessage(CMessg *msg); void CloseSocket();public: static int GetLocalHostName(CString &sHostName); /获得本地计算机名称 static int GetIpAddress(const CString &sHostName, CString &sIpAddress); /获得本地 IP static int GetIpAddress(const CString &

30、;sHostName,BYTE &f0, BYTE &f1,BYTE &f2,BYTE &f3); /获得本地 IP static CString ErrorReason(int tag);public: virtual void OnReceive(int nErrorCode); virtual void OnClose(int nErrorCode);public: CClientSocket(); virtual CClientSocket();protected:;. . . . 19 / 68CClientSocket.CPPCClientSocke

31、t.CPP 中的代码:中的代码:#include stdafx.h#include chat.h#include ClientSocket.h#includeChatDlg.h/ CClientSocketCClientSocket:CClientSocket() m_aSessionIn=NULL;m_aSessionOut=NULL; m_sfSocketFile=NULL; m_bInit=false; m_bClose=false;CClientSocket:CClientSocket() if(m_aSessionIn) delete m_aSessionIn; if(m_aSess

32、ionOut) delete m_aSessionOut; if(m_sfSocketFile) delete m_sfSocketFile;/ClientSocket 成员函数void CClientSocket:OnReceive(int nErrorCode) CSocket:OnReceive(nErrorCode); /OnReceive()函数的实现. . . . 20 / 68 do CMessg temp; temp.Serialize(*m_aSessionIn); m_dlg-m_sMsgList+=temp.m_strText+rn;m_dlg-m_tmpMsgList=

33、temp.m_strText+rn;m_dlg-SetDlgItemText(IDC_SHOWTEXT,m_dlg-m_sMsgList);FILE* fp;fp = fopen(chatnote.txt,a+);fputs(m_dlg-m_tmpMsgList,fp);fclose(fp); m_dlg-SetDlgItemText(IDC_SHOWTEXT,m_dlg-m_sMsgList); int linenum=(CEdit*) (m_dlg-GetDlgItem(IDC_SHOWTEXT)-GetLineCount(); (CEdit*) (m_dlg-GetDlgItem(IDC

34、_SHOWTEXT)-LineScroll(linenum); if(!m_dlg-m_bClient) for(POSITION pos=m_dlg-m_connectionList.GetHeadPosition(); pos!=NULL;) CClientSocket *t=(CClientSocket*) m_dlg-m_connectionList.GetNext(pos); if(t-m_hSocket!=this-m_hSocket) t-SendMessage(&temp);. . . . 21 / 68 while(!m_aSessionIn-IsBufferEmpt

35、y();void CClientSocket:Init(CChatDlg *dlg) m_sfSocketFile=new CSocketFile(this); m_aSessionIn=new CArchive(m_sfSocketFile,CArchive:load); m_aSessionOut=new CArchive(m_sfSocketFile,CArchive:store); m_bClose=false; this-m_dlg=dlg;/*SendMessage()函数的实现*主要功能:*将信息串行化*/BOOL CClientSocket:SendMessage(CMessg

36、 *msg) if(m_aSessionOut!=NULL) msg-Serialize(*m_aSessionOut); m_aSessionOut-Flush(); return TRUE;. . . . 22 / 68 else m_bClose=true; /对方关闭了连接 CloseSocket(); m_dlg-CloseSessionSocket(); return FALSE; /*CloseSocket()函数的实现*主要功能:*关闭套接字的连接*/void CClientSocket:CloseSocket() if(m_aSessionIn) delete m_aSess

37、ionIn; m_aSessionIn=NULL; if(m_aSessionOut) delete m_aSessionOut; m_aSessionOut=NULL; if(m_sfSocketFile) delete m_sfSocketFile;. . . . 23 / 68 m_sfSocketFile=NULL; Close(); m_bInit=false; m_bClose=true;/*OnClose()函数的实现*主要功能:*关闭套接字的连接*/void CClientSocket:OnClose(int nErrorCode) m_bClose=true; CloseSo

38、cket(); m_dlg-CloseSessionSocket(); CSocket:OnClose(nErrorCode);/*GetLocalHostName()函数的实现*主要功能:*获得本地计算机的名称*/int CClientSocket:GetLocalHostName(CString &sHostName) char szHostName256; int nRetCode; nRetCode=gethostname(szHostName,sizeof(szHostName); if(nRetCode!=0). . . . 24 / 68 /产生错误 sHostName=

39、_T(没有取得); return GetLastError(); sHostName=szHostName; return 0;/*GetIpAddress()函数的实现*主要功能:*取得本地 IP 地址*/int CClientSocket:GetIpAddress(const CString &sHostName,CString &sIpAddress) /获得本地 IP struct hostent FAR *lpHostEnt=gethostbyname(sHostName); if(lpHostEnt=NULL) /产生错误 sIpAddress=_T(); retu

40、rn GetLastError(); LPSTR lpAddr=lpHostEnt-h_addr_list0; if(lpAddr) struct in_addr inAddr; memmove(&inAddr,lpAddr,4); sIpAddress=inet_ntoa(inAddr); /转换为标准格式 if(sIpAddress.IsEmpty(). . . . 25 / 68 sIpAddress=_T(没有取得); return 0;/* GetIpAddress ()函数的实现*主要功能:*获得本地 IP 地址*/int CClientSocket:GetIpAddres

41、s(const CString &sHostName,BYTE &f0, BYTE &f1,BYTE &f2,BYTE &f3)/获得IP 地址 struct hostent FAR *lpHostEnt=gethostbyname(sHostName); if(lpHostEnt=NULL) /产生错误 f0=f1=f2=f3=0; return GetLastError(); LPSTR lpAddr=lpHostEnt-h_addr_list0; /获取 IP if(lpAddr) struct in_addr inAddr; memmove(&a

42、mp;inAddr,lpAddr,4); f0=inAddr.S_un.S_un_b.s_b1; f1=inAddr.S_un.S_un_b.s_b2; f2=inAddr.S_un.S_un_b.s_b3; f3=inAddr.S_un.S_un_b.s_b4; . . . . 26 / 68 return 0;CString CClientSocket:ErrorReason(int tag) /错误信息的宏定义 CString result; switch(tag) case WSANOTINITIALISED: result=A successful AfxSocketInit mus

43、t occur before using this API.; break; case WSAENETDOWN: result=The network subsystem failed; break; case WSAEADDRINUSE: result=The specified address is already in use; break; case WSAEINPROGRESS: result=A blocking Windows Socket call is in progress; break; case WSAEADDRNOTAVAIL: result=The specifie

44、d address is not available from the local machine; break; case WSAEAFNOSUPPORT: result=Address in the specified family cannot be used with this socket;. . . . 27 / 68 break; case WSAECONNREFUSED: result=The attempt to connect eas rejected; break; case WSAEDESTADDRREQ: result=A destination address is

45、 requireed; break; case WSAEFAULT: result=The nSockAddrLen arguement is incorrect; break; case WSAEINVAL: result=Invalid host address; break; case WSAEISCONN: result=The socket is already connected; break; case WSAEMFILE: result=No more file descriptions are available; break; case WSAENETUNREACH: re

46、sult=The network cannot be reached from this host at this time; break; case WSAENOBUFS: result=No buffer space is available.The socket cannot be connected; break; case WSAENOTSOCK: result=The descriptor is not a socket;. . . . 28 / 68 break; case WSAETIMEDOUT: result=Attempt to connect timed out wit

47、hout establishing a connection; break; case WSAEWOULDBLOCK: result=The socket is marked as nonblocking and the connnection cannot be completed immediately; break; default: result=unknown error; return result;CServerSocketCServerSocketCServerSocket 主要功能是实现 OnAccept()消息,负责监听服务窗口,是一个服务 socket。CServerSo

48、cket.h 的代码如下:/ CServerSocket command targetclass CChatDlg;class CServerSocket: public CSocketpublic: CServerSocket(); virtual CServerSocket(); CChatDlg *m_dlg;. . . . 29 / 68 UINT m_uPort; BOOL Init(UINT port,CChatDlg *dlg);public: virtual void OnAccept(int nErrorCode); /用于响应 OnAccept 消息的函数;CServerS

49、ocket.CPPCServerSocket.CPP 的代码如下:的代码如下:#include stdafx.h#include chat.h#include ServerSocket.h#include ChatDlg.h/ CServerSocketCServerSocket:CServerSocket()CServerSocket:CServerSocket()/CServerSocket 成员函数BOOL CServerSocket:Init(UINT port,CChatDlg *dlg) m_uPort=port; m_dlg=dlg; if(Create(m_uPort)=FAL

50、SE) AfxMessageBox(_T(Server Socket Create Error);. . . . 30 / 68 return FALSE; if(this-Listen()=FALSE) AfxMessageBox(Server Listen Error); return FALSE; m_dlg-SetDlgItemText(IDC_SHOWTEXT,Serverr Has Been Set OK!); return TRUE; void CServerSocket:OnAccept(int nErrorCode) m_dlg-ProcessPendingAccept();

51、 CSocket:OnAccept(nErrorCode);CMessgCMessgCMessg 类主要作用是实现信息的串行化,方便信息的传输。CMessg.h 代码如下:#pragma onceclass CMessg:public CObject /命令目标protected: DECLARE_DYNCREATE(CMessg)public:. . . . 31 / 68 CMessg();public: CString m_strText;public: void Init();public: virtual CMessg(); virtual void Serialize(CArchi

52、ve &ar); /实行串行化#if def_DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext &dc) const;#endif;CMessg.CPPCMessg.CPP 代码如下:代码如下:#include stdafx.h#include chat.h#include Messg.h/ Construction/DestructionIMPLEMENT_DYNCREATE(CMessg,CObject)CMessg:CMessg() Init();CMessg:CMessg()/C

53、Messg 成员函数. . . . 32 / 68void CMessg:Init() m_strText = _T();/CMsg serializationvoid CMessg:Serialize(CArchive &ar) if (ar.IsStoring() arm_strText; /CMsg diagnostics#if def_DEBUGvoid CMessg:AssertValid() const CObject:AssertValid();void CMessg:Dump(CDumpContext&dc) const CObject:Dump(dc);#en

54、dif. . . . 33 / 68CChatDlgCChatDlgCChatDlg 类负责调度整个工程,实现界面消息的添加与响应,组织整个工程的运行。1) 程序开始运行,进行对话框的初始化是在 OnInitDialog()函数中实现的,在开始的时候自动获得本地机器的 IP 地址并显示在 IP Address Control 控件中。2) 连接服务器按钮消息的响应函数。完成服务器的连接,调用CClientSocket 类的 Connect 函数来实现,同时对连接返回的信息进行处理。3) 建立服务器按钮信息的响应函数。4) 发送按钮消息的响应函数。读取文本框中的信息,调用 CMessg 类的函数

55、以实现信息的串行化,然后再调用 CClientSocket 类的SendMessage()函数将信息发送给建立连接的对方。ChatDlg.h 代码如下:/ CChatDlg dialog#include ClientSocket.h#include ServerSocket.h/CChatDlg 对话框class CChatDlg : public CDialog/构造public: CChatDlg(CWnd* pParent = NULL); /标准构造函数 /对话框数据 enumIDD=IDD_CHAT_DIALOG;protected: virtual void DoDataExcha

56、nge(CDataExchange *pDX);protected: HICON m_hIcon; /生成的消息映射函数 virtual BOOL OnInitDialog();. . . . 34 / 68 afx_msg void OnSysCommand(UINT nID,LPARAM lParam); afx_msg void OnPaint(); /afx_msg void OnInputText(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP()public: CString m_sInputText;public

57、: CString name;public: CString m_sShowString;public:UINT m_uPort; /添加的变量public: bool m_bInit; bool m_bClient; CClientSocket m_clientsocket; CServerSocket m_pListenSocket; CPtrList m_connectionList; CString m_sMsgList;CString m_tmpMsgList;public: void ProcessPendingAccept(); void CloseSessionSocket()

58、; void ClearContent(); void OnClearconnection();public: afx_msg void OnBnClickedConnect();. . . . 35 / 68public: afx_msg void OnBnClickedSetserver();public: afx_msg void OnBnClickedButton1();CChatDlg.CPPCChatDlg.CPP 代码如下:代码如下:#include stdafx.h#include chat.h#include chatDlg.h#ifdef _DEBUG#define new

59、 DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CAboutDlg dialog used for App Aboutint TouXiangNum=0;CString LiaoTianJiLu;class CAboutDlg:public CDialog. . . . 36 / 68public: CAboutDlg(); enumIDD=IDD_ABOUTBOX;protected: virtual void DoDataExchange(CDataExchange *pDX);protected: DECL

60、ARE_MESSAGE_MAP();CAboutDlg:CAboutDlg():CDialog(CAboutDlg:IDD)void CAboutDlg:DoDataExchange(CDataExchange *pDX) CDialog:DoDataExchange(pDX); BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)END_MESSAGE_MAP()CChatDlg:CChatDlg(CWnd *pParent /*=NULL*/) :CDialog(CChatDlg:IDD,pParent)m_sInputText=_T(); name=_T();m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME); /加载图标 m_sShowString=_T(); m_uPort=5000; m_hI

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论