局域网聊天程序设计方案_第1页
局域网聊天程序设计方案_第2页
局域网聊天程序设计方案_第3页
局域网聊天程序设计方案_第4页
局域网聊天程序设计方案_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

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

文档简介

1、基于局域网聊天程序设计 摘 要: 本论文讨论了 Windows 环境下局域网聊天程序的设计思路和设计 方法。其中网络通信部分采用流行的 TCP/IP 协议。程序采用典型的 C/S( 服务 器 /客户端 ) 构架。用 socket 编程设计网络通讯。界面设计部分采用 Windows MFC 框架。数据库采用微软 SQL Server 。本文最终设计了一个简易版本的聊 天软件,包括登陆、退出、添加好友、消息收 /发等功能。 关键词:Sockets API , C/S 构架,SQL Server。 Realization of a kind of LAN chat tool Abstract: Th

2、is article discusses how to design and develop a LAN chatting program in Windows environment. The network communication part depends on the popular TCP/IP protocol. Software is based on C/S architecture. Network communication is developed with Socket. UI is designed with Windows MFC frame. Database

3、is designed with SQL server. The articledescribesa concise chart software version, with the function of logging in/out, adding friend to list, sending/receiving message and so on. Key words: Sockets API ,C/S architecture,SQL Server 论文目录 局域网聊天程序的设计 错误!未定义书签。 第一章、概述 3 第二章、WINDOWSOCKETS络编程的研究错误!未定义书签。

4、2.1 TCP/IP 体系结构 5 2.2.1 TCP/IP 简介 5 2.2.2TCP/IP 的特点 5 2.2 基本套接字 5 2.3 客户机 / 服务器模式 7 2.4 WINDOWS SOCKET程序设计 8 241 WINDOWS SOCKETS AP简介 8 2.4.2WINDOWS SOCKET机制 9 第三章、网络通信模块分析 错误!未定义书签。 3.1 网络通信程序设计过程 11 3.2 网络通信程序设计核心 13 3.2.1 通信设计代码分析 13 3.2.2 数据传输代码分析 17 3.2.3 出错处理 19 第四章、界面模块分析 20 4.1 服务器端界面模块分析 20

5、 4.2 客户端界面模块分析 21 4.2.1 用户登陆界面分析 21 4.2.2 用户注册界面分析 22 4.2.3 在线用户列表界面分析 错误!未定义书签。 4.2.4 用户聊天界面分析 错误!未定义书签。 第五章、数据库模块分析 错误!未定义书签。 5.1 数据库的选择 27 5.2 数据库访问方法 错误!未定义书签。 5.3 ADO 数据库编程 错误!未定义书签。 5.3.1 ADO与 ADO接口简介错误!未定义书签。 532使用ADC操作SQL代码分析错误!未定义书签。 第六章、总结 33 6.1 体会和感想 33 6.2 总结 33 第七章、参考书目 错误!未定义书签。 第一章 概

6、述 即时通讯软件的出现正在逐渐改变人们的沟通与交际方式。无论近在咫 尺,还是远隔重洋,也只是在键盘和鼠标之间就可以解决问题。即时通讯服务 非常适合企业内部或企业和客户之间的交流。而且将即时通讯服务和手机移动 等服务结合,将更大地提高工作效率。网络聊天程序 . 越来越影响着我们的网络 生活。 习惯了通过类似ICQ、QQ MSN之类的程序和天南海北的朋友聊天、发信 息,不过所有聊天程序都需要 Internet 的支持,而无法在局域网内部“大显身 手”,那么你是否想到过要让单位内部的员工,寝室周围的同学,不用上 Internet 就可以轻松体验到内网聊天的快乐呢?有了这种想法,开发局域网聊 天程序就

7、有了必要性,让单位员工或寝室同学不出内网就能自由聊天! 本文主要研究的是一个具有高度实用性的聊天程序软件的设计原理,思路 和过程。通过该网络程序的编制和实践,对自己所学习的知识进行一次综合和 提高,有更深层次的理解和掌握,在这过程中激发自己学习的潜力,提高软件 开发的能力,加深对网络协议和 windows 环境下网络编程的理解和掌握。 第二章、 Windows Socket 网络编程的研究 2.1 TCP/IP 体系结构 2.2.1 TCP/IP 简介 TCP/IP 作为 Internet 的核心协议,通过近二十多年的发展已日渐成熟, 并被广泛应用于局域网和广域网中,目前已成为事实上的国际标准

8、。 TCP/IP 协 议集确立了 Internet 的技术基础。 TCP/IP 协议主要作用于 OSI 网络参考模型中的网络层(第 3 层)、传输 层(第 4 层)和应用层(第 7 层)。数据链路层(第 2 层)的功能主要应用于 其它协议如以太网(Ethernet )、ATM 帧中继(Frame Relay),以及多数供 应商特定协议等。 TCP/IP 充分支持所有通用第 2 层协议。 TCP/IP 组中的应用 程序通常直接运行于传输层协议 TCP 或 UDP 上面,并不需要表示层(第 6 层)和会话层(第 5 层)的支持。 2.2.2 TCP/IP 的特点 TCP/IP协议的核心部分是传输层

9、协议(TCP、UDP)网络层协议(IP)和物理 接口层,这三层通常是在操作系统内核中设计。因此用户一般不涉及。编程 时,编程界面有两种形式:一、是由内核心直接提供的系统调用;二、使用以 库函数方式提供的各种函数。前者为核内设计,后者为核外设计。用户服务要 通过核外的应用程序才能设计,所以要使用套接字 (socket) 来设计。 2.2 基本套接字 下面给出几个基本的套接字,这些套接字的使用贯穿了网络编程的始末,主 导了数据通信的过程。这将在以后的篇幅中会给出更详细的使用说明。 1、创建套接字 socket() 功能:使用前创建一个新的套接字 格式: SOCKET PASCAL FAR sock

10、et(int af,int type,int procotol)。 参数: af: 通信发生的区域 type: 要建立的套接字类型 procotol: 使用的特定协议 2、指定本地地址 bind() 功能:将套接字地址与所创建的套接字号联系起来。 格 式: int PASCALFAR bind(SOCKET s,const struct sockaddr FAR name,int namelen) 。 参数: s: 是由 socket() 调用返回的并且未作连接的套接字描述符(套接字 号)。 其它:没有错误, bind() 返回 0,否则 SOCKET_ERROR 地址结构说明: struct

11、 sockaddr_in short sin_family 。AF_INET u_short sin_port 。 /16 位端口号,网络字节顺序 struct in_addr sin_addr 。 /32 位 IP 地址,网络字节顺序 char sin_zero8 。 / 保留 3、建立套接字连接 connect() 和 accept() 功能:共同完成连接工作 格式: int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen) 。 SOCKETPASCALFAR accept(SOCKET s,

12、struct sockaddr FAR * name,int FAR * addrlen) 。 参数:同上 4、监听连接 listen() 功能:用于面向连接服务器,表明它愿意接收连接。 格式:int PASCAL FAR listen(SOCKET s, int backlog)。 5、数据传输 send() 与 recv() 功能:数据的发送与接收 格式 :int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags) 。 int PASCAL FAR recv(SOCKET s,const char FAR * b

13、uf,int len,int flags) 。 参数: buf: 指向存有传输数据的缓冲区的指针。 6、多路复用 select() 功能:用来检测一个或多个套接字状态。 格式: int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds, fd_set FAR * exceptfds,const struct timeval FAR * timeout)。 参数: readfds: 指向要做读检测的指针 writefds: 指向要做写检测的指针 exceptfds: 指向要检测是否出错的指针 timeout

14、: 最大等待时间 7、关闭套接字 closesocket() 功能:关闭套接字 s 格式: BOOL PASCAL FAR closesocket(SOCKET s。) 2.3 客户机 /服务器模式 在 TCP/IP 网络中两个进程间的相互作用的主机模式是客户机 / 服务器模式 (Client/Server model) 。该模式的建立基于以下两点: 1、非对等作用; 2、通 信完全是异步的。客户机 / 服务器模式在操作过程中采取的是主动请示方式: 首先服务器方要先启动,并根据请示提供相应服务,过程如下所示: 1、打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请 求。 2、等待

15、客户请求到达该端口 3、接收到重复服务请求,处理该请求并发送应答信号。 4、返回第二步,等待另一客户请求 5、关闭服务器。 客户方: 1、打开一通信通道,并连接到服务器所在主机的特定端口。 2、向服务器发送服务请求报文,等待并接收应答;继续提出请求 3、请求结束后关闭通信通道并终止。 2.4 WINDOWS SOCKE程S序设计 2.4.1 WINDOWS SOCKETS AP简介 VC+寸网络编程的支持有 socket支持,Winlnet支持,MAPI和ISAPI支持 等。其中, Windows Sockets API 是 TCP/IP 网络环境里,也是 Internet 上进 行开发最为通

16、用的API。最早美国加州大学 Berkeley分校在UNIX下为TCP/IP 协议开发了一个 API,这个API就是著名的Berkeley Socket 接口 (套接字)。 在桌面操作系统进入 Windows时代后,仍然继承了 Socket方法。在TCP/IP网 络通信环境下, Socket 数据传输是特殊的 I/O ,它也相当于文件描述符,具有 一个类似于打开文件的函数调用 -socket() 。可以这样理解: Socket 实际上是 一个通信端点,通过它,用户的 Socket 程序可以通过网络和其他的 Socket 应 用程序通信。 Socket 存在于一个 通信域 ( 为描述一般的线程如

17、何通过 Socket 进行通信而引入的抽象概念 )里,并且与另一个域的 Socket 交换数据。 Socket 有三类。第是 SOCK_STREA流式),提供面向连接的可靠的通信服务,比如 telnet,http 。第二种是SOCK_DGRAM据报),提供无连接不可靠的通信,比 如UDP第三种是SOCK_RA原始),主要用于协议的开发和测试,支持通信底 层操作,比如对IP和ICMP的直接访问。 2.4.1 WINDOWS SOCKET机 希 9 1 、异步选择机制: WINDOWS SOCKE异步选择函数提供了消息机制的网络事件选择,当使 用它登记网络事件发生时,应用程序相应窗口函数将收到一个

18、消息,消息中指 示了发生的网络事件,以及与事件相关的一些信息。 WINDOWS SOCKE提供了一个异步选择函数 WSAAsyncSelect(),用它来注 册应用程序感兴趣的网络事件,当这些事件发生时,应用程序相应的窗口函数 将收到一个消息。 函数结构如下: int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent) 。 参数说明: hWnd窗口句柄 wMsg需要发送的消息 lEvent :事件(以下为事件的内容) 值: 含义: FD_READ期望在套接字上收到数据(即读准备好)时接到通知 F

19、D_WRITE期望在套接字上可发送数据(即写准备好)时接到通知 FD_OOB期望在套接字上有带外数据到达时接到通知 FD_ACCEP期望在套接字上有外来连接时接到通知 FD_CONNEC期望在套接字连接建立完成时接到通知 FD_CLOS期望在套接字关闭时接到通知 例如:我们要在套接字读准备好或写准备好时接到通知,语句如下: rc=WSAAsy ncSelect(s,hWnd,wMsg,FD_READ|FD_WRIT。) 如果我们需要注销对套接字网络事件的消息发送,只要将 lEvent 设置为 0 。 2、异步请求函数 在Berkeley Sockets中请求服务是阻塞的,WINDOWS SIC

20、KETS 了支持 这一类函数外,还增加了相应的异步请求函数 (WSAAsyncGetXByY(。) )。 3、阻塞处理方法 WINDOWS SOCKE为了设计当一个应用程序的套接字调用处于阻塞时,能 够放弃CPU让其它应用程序运行,它在调用处于阻塞时便进入一个叫“HOO” 的例程,此例程负责接收和分配 WINDOW消息,使得其它应用程序仍然能够接 收到自己的消息并取得控制权。 WINDOW是非抢先的多任务环境,即若一个程序不主动放弃其控制权,别 的程序就不能执行。因此在设计 WINDOWS SOCKE程序时,尽管系统支持阻塞 操作, 但还是反对程序员使用该操作。 但由于 SUN 公司下的 Be

21、rkeley Sockets的套接字默认操作是阻塞的,WINDOW作为移植的SOCKETS也不可避 免对这个操作支持。 在WINDOWS SOCKE设计中,对于不能立即完成的阻塞操作做如下处理: DLL初始化一循环操作。在循环中,它发送任何WINDOWS肖息,并检查这个 WINDOWS SOCKE用是否完成,在必要时,它可以放弃CPU让其它应用程序 执行(当然使用超线程的CPU就不会有这个麻烦了)。我们可以调用 WSACancelBlockingCall() 函数取肖此阻塞操作。 在WINDOWS SOCKETS有一个默认的阻塞处理例程 BlockingHook() 简单地 获取并发送 WIN

22、DOW消息。如果要对复杂程序进行处理,WINDOWS SOCKE中S 还有 WSASetBlockingHook() 提供用户安装自己的阻塞处理例程能力;与该函 数相对应的则是SWAUnhookBlockingHook(),它用于删除先前安装的任何阻塞 处理例程,并重新安装默认的处理例程。请注意,设计自己的阻塞处理例程 时,除了函数 WSACancelBlockingHook() 之外,它不能使用其它的 WINDOWS SOCKETS AP函数。在处理例程中调用 WSACancelBlockingHook()函数将取消 处于阻塞的操作,它将结束阻塞循环。 4、出错处理 WINDOWS SOCK

23、E为了和以后多线程环境( WINDOWS/UNIX兼容,它提供 了两个出错处理函数来获取和设置当前线程的最近错误号。( WSAGetLastEror() 和 WSASetLastError() ) 5、启动与终止 使用函数 WSAStartup() 和 WSACleanup() 启动和终止套接字 第三章、网络通信模块分析 3.1 网络通信程序设计过程 在调用了 Windows sockets的启动函数 WSACIeanup(之后才能进行其他的 Socket 系统调用,但启动函数 WSAStartup() 是为了建立与 Windows Sockets DLL 的连接,因此在 VC+6.0 所建立

24、工程的工程设置中的连接的库模块必须进 行设置,在其中的link栏内的对象/库模块中加入“ Ws2_32.lib ”,才能真正 建立建立与 Windows Sockets DLL 的连接。 其他的Socket系统调用包括创建Socket、将创建的Socket与本地端口绑 定、建立 Socket 连接服务器、监听是否有连接、请求数据的可控缓冲发送和可 控缓冲接收,到最后关闭Socket。具体流程图如1所示。 首先在服务器方,利用 socket() 函数建立流式套接字,返回套接字号 s, 接着利 用 bind() 函数将套接字 s 与本地地址绑定,紧接着利用 listen(0 函数通知 TCP, 监

25、听客户方, 服务器准备接收连接, 没有连接的话, 服务器方通过 closesocket() 关闭套接字 s, 服务结束。有连接的话 ,在客户方,通过 socket() 函数建立流式套接字 s, 此时在服务器方,建立连接,通过 accept() 返回,得到 新的套接字 ns, 客户方通过 connect() 将套接字 s 与远程地址连接 , 此时服务器 方/客户方在 ns/s 上读/ 写数据,直到交换完成。交换完成后,服务器方 / 客户 方关闭套接字 ns/s, 最后服务器方通过 closesocket() 关闭最初套接字 s, 服务 结束。 具体设计过程如图 1 所示,具体设计代码将会在下面介

26、绍: 面向连接的套接字的系统调用流程图 3.2 网络通信程序设计核心代码分析 3.2.1 通信设计代码分析 先分析服务器端。 首先定义初始化网络函数,也就是 WINDOWS SOCKETS 的启动 在所有 WINDOWS SOCKETS中,只有启动函数 WSAStartup() 和终止函 数 WSACleanup() 是必须使用的。 启动函数必须是第一个使用的函数,而且它允许指定 WINDOWS SOCKETS API的版本,并获得SOCKETS勺特定的一些技术细节。本结构如下: int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADA

27、TA lpWSAData)。 其中wVersionRequested 保证SOCKETS可正常运行的 DLL版本,如果不支 持,则返回错误信息。 设计代码如下,主要是进行 WSAStartup() 函数 的调用 WORD wVersionRequested /定义版本信息变量 WSADATA wsaData。 / 定义数据信息变量 int err 。 / 定义错误号变量 wVersionRequested = MAKEWORD(1,1) 。 / 给版本信息赋值 err = WSAStartup(wVersionRequested, &wsaData) 。 / 给错误信息赋值 if(err!=0

28、) return 。 / 告诉用户找不到合适的版本 / 确认 WINDOWS SOCKETS D支持 1.1 版本 /DLL 版本可以高于 1.1 / 系统返回的版本号始终是最低要求的 1.1 ,即应用程序与 DLL 中可支持 的最低版本号 if(LOBYTE(wsaData.wVersion)!= 1| HIBYTE(wsaData.wVersion)!=1) WSACleanup() 。 / 告诉用户找不到合适的版本 return 。 /WINDOWS SOCKETS DLL 被进程接受,可以进入下一步操作 既然启动了到最后就需要调用WSACIeanup(函数来终止,关闭函数使用时,任 何

29、打开并已连接的 SOCK_STREA套接字被复位,但那些已由closesocket() 函数关闭的但仍有未发送数据的套接字不受影响,未发送的数据仍将被发送。 程序运行时可能会多次调用 WSAStartuo() 函数,但必须保证每次调用时的 wVersionRequested 的值是相同的。 接着是创建服务器端套接字,主要代码如下: SOCKET ServerSock。 / 服务器端 Socket ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 。 if(ServerSock MessageBox( 创 建 套 closesocket

30、(ServerSock) WSACleanup() return 套接字创建好之后就是与本地地址绑定: sockaddr_in localaddr 。 localaddr.sin_family = AF_INET 。 localaddr.sin_port = htons(8888) 突 INVALID_SOCKET) 接 字 失 败 !)。 。 。 FALSE。 file:/ 端口号不要与其他应用程序冲 if(bind(ServerSock ,(struct sockaddr*)&localaddr,sizeof(sockaddr) = = SOCKET_ERROR) MessageBox(绑

31、定地址失败!)。 closesocket(ServerSock) 。 WSACleanup()。 return FALSE 。 接下来就是对SOCKE的设置,本程序使用的数据传输模式是异步非阻塞模式, 设置好之后就是监听客户端信息,主要代码如下 if(WSAAsyncSelect(ServerSock, m_hWnd, NETWORK_EVENT, FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE) = SOCKET_ERROR) MessageBox(注册网络异步事件失败!)。 WSACleanup()。 return FALSE 。 listen(Serv

32、erSock, 5)。 / 设置侦听模式 return TRUE 。 其中m_hWnc为应用程序的主对话框或主窗口的句柄。 这就要说到网络异步函数的回调函数,主要代码内容如下: OnNetEvent(WPARAM wParam, LPARAM lParam) / 调用 Winsock API 函数,得到网络事件类型 int iEvent = WSAGETSELECTEVENT(lParam)。 / 调用 Winsock API 函数,得到发生此事件的客户端套接字 SOCKET CurSock= (SOCKET)wParam switch(iEvent) case FD_ACCEPT: / 客户

33、端连接请求事件 OnAccept(CurSock) 。 break 。 case FD_CLOSE: / 客户端断开事件 : OnClose(CurSock) 。 break 。 case FD_READ: / 网络数据包到达事件 OnReceive(CurSock) 。 break 。 case FD_WRITE: / 发送网络数据事件 OnSend(CurSock)。 break 。 default: break 。 另外,发生在相应 Socket 上的各种网络异步事件的处理函数,其中 OnAccept 传进来的参数是服务器端创建的套接字, OnClose() 、OnReceive() 和

34、 OnSend() 传进来的参数均是服务器端在接受客户端连接时新创建的用与此客户端通信的 Socket 。定义 OnAccept() 函数来接受连接请求,并保存与发起连接请求的客户 端进行通信Socket,为新的socket注册异步事件。定义 OnSend()函数来给客 户端发数据时做相关预处理。 定义 OnReceive() 函数来读出网络缓冲区中的数 据包。定义 OnClose() 函数来结束与相应的客户端的通信,释放相应资源。 接下来讲讲客户端方。 首先初始化网络部分,带不需要将套接字设置为监听模式。注册异步事件时, 没有FD_ACCEPT但增加了 FD_CONNE事件,因此没有 OnA

35、ccept()函数,但增 加了 OnConnect() 函数。向服务器发出连接请求时,使用 connect() 函数,连接 成功后,会响应到 On Co nn ect()函数中。下面是 OnConn ect()函数的定义,传进 来的参数是客户端 Socket 和服务器端发回来的连接是否成功的标志。 void CXFQQClientDlg:OnConnect(SOCKET CurSock, int error) if(0 = = error) if(CurSock = = ClntSock) MessageBox(连接服务器成功!)。 另外定义On Receive。函数来处理网络数据到达事件。定

36、义On Se nd()函数来处 理发送网络数据事件。定义 OnClose()函数来处理服务器的关闭事件。 3.2.2 数据传输代码分析 在服务器方用WSASend()函数来发送数据,使用 WSARecv()来接收数据。 Windows Sockets 不鼓励用户使用阻塞方式传输数据,因为那样可能会阻塞整 个 Windows 环境。发送数据主要代码如下所示: if (WSASend(pSI-s, &(pSI-wsaBuf), 1,&dwSendBytes, 0,&(pSI-o), NULL) = SOCKET_ERROR) if (WSAGetLastError() != ERROR_IO_PE

37、NDING) PrintSystemError(WSASend() 失败) 。 / 自定义出错显示 函数 return -1。 其中 pSI 的类型是自定义的网络信息结构,包含网络的所有信息。结构定 义如下: typedef struct char buffRecvDATA_BUFSIZE 。 char buffSendDATA_BUFSIZE 。 WSABUF wsaBuf/指向WSABU拮构数组的指针 SOCKET s / 标识一个已连接套接口的描述字。 WSAOVERLAPPED/O 指向 WSAOVERLAPPED 结构的指针 DWORD dwBytesSend DWORD dwByt

38、esRecv int nStatus 。 char ip16。 BOOL bLoggedIn。 SOCKET_INF,*LPSOCKET_INF 若无错误发生且发送操作立即完成,则WSASe nd(函数返回所发送的字节 数。(注意该数目可能小于 len 参数所指定的值)。如果连接结束,则返回 0。请注意在这种情况下完成指示(启动指定的完成例程或设置一个事件对象) 将早已发生。否则的话,将返回SOCKET_ERROR误,应用程序可通过 WSAGetLastError() 来获取相应的错误代码 , 返回 -1。错误代码 WSA_IO_PENDING 表示重叠操作成功启动,过后将有完成指示。任何其他

39、的错误表示重叠操作未 能成功地启动,以后也不会有完成指示。 服务器方接收数据代码如下: if (WSARecv(pSI-s, &(pSI-wsaBuf), 1, &dwRecvBytes, &dwFlags,&(pSI-o), NULL) = SOCKET_ERROR) if (WSAGetLastError() != ERROR_IO_PENDING) PrintSystemError(WSARecv() 失败) 。 return -1 。 若无错误发生且接收操作立即完成,则WSARecv(函数返回所接收的字节 数。如果连接结束,则返回0。请注意在这种情况下完成指示(启动指定的完 成例程或设

40、置一个事件对象)将早已发生。否则的话,将返回SOCKET_ERR错R 误,应用程序可通过 WSAGetLastError() 来获取相应的错误代码。错误代码 WSA_IO_PENDIN表示重叠操作成功启动,过后将有完成指示。任何其他的错误 表示重叠操作未能成功地启动,以后也不会有完成指示。 在客户方,利用 send() 和 recv() 来发送和接收消息, 发送代码如下 : if(send(m_cliSocket,buff,sizeof(buff),0) = SOCKET_ERROR) closesocket(m_cliSocket) 。 return 。 若无错误发生, send() 返回所

41、发送数据的总数(请注意这个数字可能小于 len中所规定的大小)。否则的话,返回SOCKET_ERR错误,应用程序可通过 WSAGetLastError() 获取相应错误代码。 接收代码如下: if(recv(cliSock,buff,sizeof(buff),0) = SOCKET_ERROR) closesocket(cliSock) 。 return FALSE 。 若无错误发生, recv() 返回读入的字节数。如果连接已中止,返回 0。否 则的话,返回SOCKET_ERR错误,应用程序可通过 WSAGetLastError()获取相 应错误代码。 3.2.4 出错处理 自定义 Prin

42、tSystemError 函数来显示错误信息 , 编写方式如下: void PrintSystemError(CString str) char strSystemError40 。 CXFQQServerDlg *dlg=(CXFQQServerDlg*) AfxGetApp()- GetMainWnd()。 memset(strSystemError,0,sizeof(strSystemError) sprintf(strSystemError,系统:%s,str)。 dlg-m_list.l nsertStri ng(g_dwListCo un t+, strSystemError) d

43、lg-mist.SetTopl ndex(g_dwListCou nt-1)。 第四章、界面模块分析 4.1服务器端界面模块分析 服务器端界面如图2所示 图2服务器界面 如图2所示,在服务器界面设计上设计很简单,通过一个列表框来显示服 务器信息,一个启动按钮来启动服务器,一个退出按钮关闭服务器。 如果服务器启动没有什么问题就会在列表框中显示“创建服务器成功”字 样。 当用户登陆,就会在列表框中显示如“ 连接,接受 : USER 1001 接受 : PASS 1001 三行字样,如果登陆成 功,在列表框中就会显示“接受 127.0.0.

44、1 : LIST”字样,获取在线用户列 表。如果登陆失败,在列表框中就会显示如“断开”字样。 在注册用户的时候,如果注册成功,在列表框中就会显示如“ADD USER 1001 SUCCESS ,如果失败,就会在列表框中显示“ ADD USER FAIL 当修改用户信息的时候就会在列表框中显示“接受 : GINF 1001” ,如果修改成功,就会在列表框中显示“接受: UINF 1001”。 4.2客户端界面模块分析 客户端界面主要包括用户登陆界面、用户注册界面、在线用户列表界面、 用户聊天界面。 其中客户端界面设计思路,主要设计过程如图3所

45、示: 图3客户端界面轮廓 4.2.1用户登陆界面分析 用户登陆界面如图4所示 Xl 用户号码: 用户密码: 服务器IP: 厂保存窖码 取消 I 注册向导 登录 图4用户登陆界面 如图4显示,当单击“登陆”按钮进行用户的登陆: 当用户号码未填写时,会提示“请输入用户号码”。 当用户密码未填写时,会提示“请输入用户密码”。 当服务器IP未填写或格式不正确,会提示“请填写正确的服务器地址”。 勾选“保护密码”,在下次打开该登陆界面时,在输入框里自动显示上次 登陆时输入的三项信息。 用户信息填写完毕后,按“登陆”按钮,如果与服务器连接失败,就会提示如 “连接失败:不能连接上的服务器”

46、 登陆成功就会进入在线用户列表界面,如图6所示.o 单击“取消”按钮退出登陆界面。 单击“注册向导”按钮就可以进入用户注册界面,如图5所示。 4.2.2用户注册界面分析 如图4所示,单击“注册向导”按钮,进入用户注册界面。如图 5所示 图5用户注册界面 所有信息都必须填写,当某项信息未填时,会提示“请输入xxx,并在同 时将“用户密码”和“确认密码”二栏内容清空。 当点击“注册”按钮时,如果注册成功,提示“注册成功,你的用户号码 是 XXXX ” 如果注册失败,若是服务器未启动或连接失败,则会提示“注册失败,服 务器未启动或连接失败。” 单击“取消”按钮,返回登陆界面。 4.3在线用户列表界面

47、分析 如图4所示,当登陆成功时进入在线用户列表界面,如图 6所示。 -lr I x | 图6在线用户列表界面 当单击自己用户号码时,在列表下显示“修改”按钮,单击该按钮,显示图7 所示的自己的用户信息并可以进行修改。 靈認显2d 修改| 取消| 图7修改用户资料界面 能修改的所有内容格式必须正确而且不能未空,否则单击“修改”后会提 示“修改没有成功! ”修改成功就会提示“修改成功”,但不管成功与否,都 会返回用户列表界面,单击用户列表界面的“刷新”按钮,如果修改成功,其 中被修改的信息会改变。单击取消按钮,返回用户列表界面 当单击其他用户号码时,在列表下显示“查看”按钮,单击该按钮,显示 如图

48、8所示的其他用户信息 图8用户信息查看界面 其他用户的所有信息都不能修改,你可以单击“加为好友”按钮来增加好 友。添加成功后会提示“增加好友成功”,否则提示“增加好友失败”。单击 “取消”按钮返回在线用户列表界面。 如图6所示,单击“进入聊天”按钮,可以进入用户聊天界面,如图 示。 424用户聊天界面分析 用户聊天界面如图9所示 图9用户聊天界面 首先选择你要聊天的好友。通过“发送”按钮发送你要讲的内容,通过 “聊天记录”按钮/ “关闭记录”按钮来显示/关闭聊天记录。单击“传送文 件”按钮,跳出文件目录,让你选择你要传送的文件。如图10所示 图10传送文件界面 第五章、数据库模块分析 5.1

49、数据库的选择 选择一个好的应用程序对一个应用系统来说是非常重要的。应用系统应该 选择哪种数据库要根据系统的要求和企业的实际情况而定。目前,所有流行的 几种大型关系型数据库有 MS SQL Server、Oracle、DB2等。本系统使用 MS SQL Server,主要有以下几点理由: 1) MS SQL Server比较容易使用,一般管理员较熟悉。 2) MS SQL Server有存储过程、视图等方便功能扩展。 5.2 数据库访问方法 本程序示通过用ADO来访问数据库,分别用ADC访问了数据库的各个对象及 各方法。 5.3 ADC数据库编程 5.3.1 ADC与 ADC接口简介 ADC是M

50、icrosoft为最新和最强大的数据访问范例 OLE DB而设计的,是 一个便于使用的应用程序层接口。ADO使您能够编写应用程序以通过 OLE. DB 提供者访问和操作数据库服务器中的数据。OLE DB是一组”组件对象模 型” (COM)接口,是新的数据库低层接口,它封装了ODBC勺功能,并以统一的 方式访问存储在不同信息源中的数据。OLE DB是 Microsoft UDA(Universal Data Access)策略的技术基础。OLE DB为任何数据源提供了高性能的访问,这 些数据源包括关系和非关系数据库、电子邮件和文件系统、文本和图形、自定 义业务对象等等。OLE DB应用程序编程接

51、口的目的是为各种应用程序提供最佳 的功能,它并不符合简单化的要求。您需要的 API 应该是一座连接应用程序和 OLE DB 的桥梁,这就是 ActiveX Data Objects (ADO) 。 ADO库包含三个基本接口:_Co nn ectio nPtr 接口、_Comma ndPtr接口和 _RecordsetPtr 接口。 _ConnectionPtr 接口返回一个记录集或一个空指针。通常使用它来创建一 个数据连接或执行一条不返回任何结果的 SQL 语句,如一个存储过程。使用 _ConnectionPtr 接口返回一个记录集不是一个好的使用方法。对于要返回记录 的操作通常用 _Reco

52、rdserPtr 来设计。而用 _ConnectionPtr 操作时要想得到记 录条数得遍历所有记录,而用 _RecordserPtr 时不需要。 _Comma ndPtr接口返回一个记录集。它提供了简单的方法来执行返回记录 集的存储过程和SQL语句。在使用_CommandPtr接口时,你可以利用全局 _ConnectionPtr 接口,也可以在_CommandPtr接口里直接使用连接串。如果你 只执行一次或几次数据访问操作,后者是比较好的选择。但如果你要频繁访问 数据库,并要返回很多记录集,那么,你应该使用全局 _ConnectionPtr 接口创 建一个数据连接,然后使用_CommandP

53、t接口执行存储过程和SQL语句。 _RecordsetPtr 是一个记录集对象。与以上两种对象相比,它对记录集提 供了更多的控制功能,如记录锁定,游标控制等。同_Comma ndPtr接口一样, 它不一定要使用一个已经创建的数据连接,可以用一个连接串代替连接指针赋 给_RecordsetPtr的conn ection 成员变量,让它自己创建数据连接。如果你要 使用多个记录集,最好的方法是同Comma nd对象一样使用已经创建了数据连接 的全局_ConnectionPtr接口,然后使用_RecordsetPtr执行存储过程和SQL语 句。 在下面的代码分析中将详细介绍 ADO怎样利用这几个接口来

54、对数据库SQL 进行操作。 532使用ADO作SQL代码分析 1、引入ADO库文件 使用ADC前必须在工程的stdafx.h头文件里用直接引入符号#import引入 ADO库文件,以使编译器能正确编译。代码如下所示: 用#import引入ADO库文件 #importc:programfilescommonfilessystemadomsado15.dllno_nam espaces rename(EOF adoEOF) 这行语句声明在工程中使用ADO但不使用ADO勺名字空间,并且为了避 免常数冲突,将常数EOF改名为adoEOF现在不需添加另外的头文件,就可以 使用 ADO接 口了。 2、初始

55、化OLE/COM库环境 必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO 前,必须初始化 OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在 应用程序主类的Initlnstanee成员函数里初始化OLE/COM库环境。 BOOL CXFQQClientAp:p :InitInstance() if(!AfxOlelnit()这就是初始化COM库 AfxMessageBox( “OLE初始化出错! ”)。 return FALSE 。 3、判断数据库的存在 使用USE语句,成功了就存在;不成功,就不存在。 代码如下: try m_pConneet-Exeeute

56、( _bstr_t(USE lNSURANCE_2002),NULL, adCmdTextl adExecuteNoRecords )。 catch (_com_error &e) blSuccess=FALSE。 CString str= 数据库 INSURANCE_200不存在! n。 str+=e.Description() 。 :MessageBox(NULL,str,警告,MB_OK | MBCONWARNING) 4、连接数据库 通过MS SQL SERVER 200创建数据库名为 XFQQ接着在ODBC中添加数据 源,数据源名为XFQQ定义一个指向 Connection对象的指针

57、:_ConnectionPtr _pConnection 。连接代码如下: HRESULT h。 try hr = m_pConnection.CreateInstance(ADODB.Connection) 。 / 创 建 Connection 对象 if(SUCCEEDED(hr) hr = m_pConnection-Open(DSN=XFQQ UID=sa。PWD= , 1)。 / 连接数据库 catch(_com_error e)/ 捕捉异常 CString errormessage 。 errormessage.Format( 连 接 数 据 库 失 败 !rn 错 误 信 息 :%s,e.ErrorMessage() 。 AfxMessageBox(errormessage) 。 / 显示错误信息 3、判断表的存在 判断一个表是否存在,可以用是否成功地打开它来判断,代码如下: try m_pRecordset-Open(_variant_t(mytable), _variant_t(IDispatch *)m_pConnection,true), adOpenKeyset, adLockOptimistic, adCmd

温馨提示

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

评论

0/150

提交评论