局域网通信工具设计实现.doc_第1页
局域网通信工具设计实现.doc_第2页
局域网通信工具设计实现.doc_第3页
局域网通信工具设计实现.doc_第4页
局域网通信工具设计实现.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

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

文档简介

计算机网络课程设计报告一:设计任务近年来,随着全球信息化进程的不断发展,网络也在飞速发展。出于高效、快速地处理各种事务的目的,越来越多的企业在其内部使用局域网来进行工作。在内部局域网的帮助下,企业得以简化信息流程,提高信息交换的速度,从而提高工作效率。然而,随着企业规模的扩大,业务量的增加,在局域网上运行的应用越来越多,如知识库、网络会议、数据库应用和数据的同步与备份等,这些应用对局域网的信息吞吐、处理能力的要求也越来越高。这些在企业内部原有局域网设计之初未曾考虑到的新情况的出现使得局域网不堪重负,容易发生信息阻塞,此时,局域网不但不能提高生产效率,反而成为企业发展的瓶颈。 为了解决上述矛盾,人们提出了许多方法。提升网络带宽及增加服务器的吞吐能力是解决此矛盾的一种方法。然而,从企业运行的成本方面考虑,无论是单纯地提升网络带宽或增加服务器的吞吐能力都不能从根本上解决局域网资源紧张的问题,对旧有局域网的大规模硬件改造反而会增加企业的负担。本文讨论一种基于Socket的局域网通信工具的设计与实现方法。基于Socket的局域网通信软件可以为局域网提供一种良好,安全,快速的通信机制。它的使用能有效地降低局域网通信负荷,提高局域网的使用效率,可以很好地解决内部局域网的各种通信需求。 基于Socket的局域网聊天工具是此类局域网通信软件的具体实例之一,它很好地诠释了Socket通信的原理,并且在局域网内部通信、教学、讨论等应用中都具有一定的实用价值。它具有信息收发速度快,保密性好,占用网络带宽资源低,占用服务器吞吐能力低,易于编程实现等优点。基于Socket的局域网通信软件应用范围广阔,不但可以处理传统的通信需求,而且也能扩展以适应新型的网络应用,如网络教育,数据影音传输等,拥有广泛的应用前景。本程序要实现设计任务(1)程序启动之后就能看到当前哪些机器在线,哪些可以与之进行对等通信。(2)一旦有某个网内的机器上线了,要有即时通知,并能及时更新用户界面中的用户列表。(3)当双击某个列表项的时候,要弹出聊天对话框,可以在其中编辑要发送的聊天信息,并进行发送。(4)聊天界面要人性化,下面是发送框,上面有已有聊天记录,并借助滚动条看到当次所有的聊天记录。(5)当有人向我发送信息的时候,要弹出一个对话框,显示用户接收到的信息,并且知道是谁人所发,并且在当前对话框内进行信息的回复。二:设计方案既然选定了WINDOWS平台,而又要开发网络通信程序,所以可以选择WINDOWS的SOCKETS编程接口,Windows Sockets是一套开放的、支持多种协议的Windows下的网络编程接口。现在的Winsock已经基本上实现了与协议无关,你可以使用Winsock来调用多种协议的功能,但较常使用的是TCP/IP协议。Winsockets无疑是我们进行网络编程的利器。通常的通信工具,都采用客户机/服务器(C/S)体系结构,C/S结构是这样的一种结构:它包括一个客户机(或前端),一个服务器(或称后端),客户机的作用是访问和处理远程服务器上的数据,服务器的作用是接收和处理客户机的数据请求。有时,可能有多个客户向同一个服务器同时请求服务,这就需要服务器决定怎样处理这些请求。Client/Server结构是当前数据库应用程序中极为流行的一种方式。尤其是网络技术的发展,使得当前很多系统都采用这种方式进行构造,其最大的优点是将计算机工作任务分别由客户端和服务器端来共同完成,这样有利于充分合理的利用系统资源。另外它的服务器端还可以将信息集中起来,任何客户机都可以通过访问服务器而获得所需的信息。Client/Server模型最终可归结为一种“请求/应答”关系。一个请求总是首先被客户发出,然后服务器总是被动地接收请求,返回客户需要的结果。在客户发出一个请求之前,服务进程一直处于休眠状态。一个客户提出请求后,服务进程被“唤醒”并且为客户提供服务,对客户的请求做出所需要的应答。但是具体到现在这个项目,如果要做成C/S结构,需要在局域网内架设一个服务器,而在一个局域网中,如果网络结构不是集中式的而是分散式的,那么可能没有一台机器来充当服务器这个角色,比如我们的校园宿舍网络就是如此。所以说,我的设计是每个程序自己既充当客户机又充当服务器,自己维护网络上的客户机列表,每两个客户端要进行连结时都直接连通而不用通过服务器来进行信息的中转,这样虽然损失了一些性能各带宽资源,但是对通信量不是很大的局域网,这点损失可以由换得的专门架设服务器的优点来弥补。通信数据的一个流向示意图不是真正的网络拓扑结构,也就是说其中的服务器可能只是装了服务器软件的一台普通工作站。在底层的数据流向中,也就是网络的物理连结,并非我们这个软件所能决定的,我们的所做都是在一个透明的数据通信层之上的。三:系统的原理框图(程序流程图)因为在本系统中,每一个客户端系统都是相同的也就是具体到通信双方而言其实是对称的,所以只需要考虑一个系统就可以了。根据以上的系统需求分析,以及体系结构设计,可以对系统进行如下的功能模块划分如图所示:其中主线程模块完成对网络的初始化,然后启动两个子线程:服务端监听线程以及网络扫描模块线程,然后由网络扫描模块得到当前的网络用户分布情况,并填充相关的数据结构,然后生成用户列表界面显示给用户。通信模块又包括两个子模块:数据接收模块和数据发送模块,这两个模块都由系统定义的网络事件来触发。输入/输出模块用来响应用户双击用户列表的某一项要准备发送信息时的消息,以及当系统接收到某个网络用户发送来的消息,要将其显示给用户的时候。网络扫描模块是由主线程模块启动,进行网络扫描,确定哪些用户当前处于可到达状态,以及哪些可到达状态的用户安装有相应的通信软件,并启动之可以与之进行通信。我觉得这样的模块划分设计符合强内聚,弱耦合的原则,并且易于实现。由于系统首先要维护一个网络用户列表,所以要设计一个数组。这个数组具体可为255行2列数组,每一行代表局域网中的一台主机,然后第一列代表其是否处于可到达状态,第二列代表其是否处于可通信状态。因为程序刚启动时的网络扫描阶段耗时较久,所以应当在程序启动后以一个人性化的界面提示用户不要以为程序无法响应了,暂时的缓慢是正常反应。因此我决定设计一个启动画面,这个启动画面可由VC+6.0提供的Splash screen组件来实现,它将向工程中插入一个类CSplashWnd.我只需要在合适的地方调用该类,并进行具体的定制即可。其它的相关类皆由MFC的应用程序向导自动生成,我只需要在其中进行具体的功能代码添加即可。四:程序设计当扫描完毕时后,在主显示界面中就会显示出局域网内所有当前在线的用户列表,并且显示哪些主机可以进行聊天。并且由于显示是即时的,也就是扫描完一台马上显示出来,并且用户可以看到当前正在扫描哪一台机器,这样的设计也是比较合理的,如下图45所示。本程序还有一个附加非常方便的功能就是上线提示,当局域网内某用户打开了对应的程序,那么就会弹出相应的提示,并即时更新用户列表。程序主显示界面 当双击列表中的某一项时,会弹出聊天对话框,来实现消息发送功能,或者当程序接收到某个网内用户发来的信息时,也要弹出对话框向用户进行显示,实际效果如下图所示:程序聊天界面服务端线程的具体作就是首先创建一个SOCKETS,然后将该套接字绑定到本地主机的某一个固定的端口上,在本程序中选择了41786端口。接着将该套接字设置为异步非阻塞模式,并为它注册各种网络异步事件,最后开始监听。具体代码如下:void CNetTestWithAPIDlg:SevThreadFunc(LPVOID lpParam)CNetTestWithAPIDlg* TempObject=(ServerParam*)lpParam-tempdlg; SOCKET tempServer=(ServerParam*)lpParam)-ServerSocket; sockaddr_in localaddr;/*/Bind to a local port localaddr.sin_family=AF_INET; localaddr.sin_port=htons(41786); localaddr.sin_addr.s_addr=0; if(bind(tempServer,(struct sockaddr*)&localaddr,sizeof(sockaddr)=SOCKET_ERROR) AfxMessageBox(绑定地址失败!); closesocket(tempServer); WSACleanup(); return ; /将SeverSock设置为异步非阻塞模式,并为它注册各种网络异步事件 if(WSAAsyncSelect(tempServer, TempObject-m_hWnd,NETWORK_EVENT,FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE) = SOCKET_ERROR) AfxMessageBox(注册网络异步事件失败!); WSACleanup(); return; listen(tempServer, 5);/设置侦听模式然后启动扫描线程:SearchDisplay(); /Serach Lan and display the result to the user!上面调用了SearchDisplay()来启动网络扫描线程,该函数的实现如下:void CNetTestWithAPIDlg:SearchDisplay()hScanThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ScanThreadFunc,this,0,&ScanThreadID);CloseHandle(hScanThread);具体的扫描过程在网络扫描模块详细设计中阐述。网络扫描模块详细设计 网络扫描基于ICMP协议,所以需要先定义两个数据结构:typedef struct unsigned char Ttl; / Time To Live unsigned char Tos; / Type Of Service unsigned char Flags; / IP header flags unsigned char OptionsSize; /Size in bytes of options data unsigned char *OptionsData; / Pointer to options data IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION;typedef struct DWORD Address; / Replying address unsigned long Status; / Reply status unsigned long RoundTripTime; / RTT in milliseconds unsigned short DataSize; / Echo data size unsigned short Reserved; / Reserved for system use void *Data; / Pointer to the echo data IP_OPTION_INFORMATION Options; / Reply options IP_ECHO_REPLY, * PIP_ECHO_REPLY;然后在网络扫描线程的线程函数中加入以下代码,完成扫描网络并显示用户列表的功能:char HostName255;PHOSTENT HostInfo;gethostname(HostName,sizeof(HostName);/get localhost infoHostInfo=gethostbyname(HostName);LPCSTRip=inet_ntoa(*(structin_addr *)*HostInfo-h_addr_list);in_addr* pip=(struct in_addr *)*HostInfo-h_addr_list;CString temp=ip;int n=0;int a=temp.Find(.);a=temp.Find(.,a+1);a=temp.Find(.,a+1);a=temp.GetLength()-a;CString temp2=temp.Right(a-1);n=atoi(temp2);HINSTANCE hIcmp = LoadLibrary(ICMP.DLL);if (hIcmp = 0) AfxMessageBox(Unable to locate ICMP.DLL!); return ;/ 装载ICMP.DLL连接库typedef HANDLE (WINAPI* pfnHV)(VOID);/定义函数三个指针类型typedef BOOL (WINAPI* pfnBH)(HANDLE);typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD); / evil, no?pfnHV pIcmpCreateFile;/定义三个指针函数 pfnBH pIcmpCloseHandle; pfnDHDPWPipPDD pIcmpSendEcho; pIcmpCreateFile = (pfnHV)GetProcAddress(hIcmp,IcmpCreateFile); pIcmpCloseHandle=(pfnBH)GetProcAddress(hIcmp,IcmpCloseHandle); pIcmpSendEcho=(pfnDHDPWPipPDD)GetProcAddress(hIcmp,IcmpSendEcho); /从ICMP.DLL中得到函数入口地址 if(pIcmpCreateFile = 0)|(pIcmpCloseHandle = 0)|(pIcmpSendEcho = 0) AfxMessageBox(Failed to get proc addr for function.); return ; HANDLE hIP = pIcmpCreateFile();/ 打开ping服务 if (hIP = INVALID_HANDLE_VALUE) AfxMessageBox(Unable to open ping service.); return ; char acPingBuffer64;/ 构造ping数据包 memset(acPingBuffer, xAA, sizeof(acPingBuffer); PIP_ECHO_REPLY pIpe=(PIP_ECHO_REPLY)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(IP_ECHO_REPLY)+sizeof(acPingBuffer); if(pIpe = 0) AfxMessageBox(Failed to allocate global ping packet buffer.); return ;pIpe-Data = acPingBuffer;pIpe-DataSize = sizeof(acPingBuffer); /构造探测41786端口的连接SocketSOCKET DetectSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);sockaddr_in remoteaddr;remoteaddr.sin_family=AF_INET; remoteaddr.sin_port=htons(41786);int n_item=0;CNetTestWithAPIDlg* TempObject=(CNetTestWithAPIDlg*)lpParam;CString ClientHostName;/ 发送ping数据包for(int i=0,row_num=0;iS_un.S_un_b.s_b4=i;char status100=0;sprintf(status,Scan %d.%d.%d.%d ing.,pip-S_un.S_un_b.s_b1,pip-S_un.S_un_b.s_b2,pip-S_un.S_un_b.s_b3,pip-S_un.S_un_b.s_b4);TempObject-GetDlgItem(IDC_STATIC_STATUS)-SetWindowText(status); DWORD dwStatus = pIcmpSendEcho(hIP, *(DWORD*)pip), acPingBuffer, sizeof(acPingBuffer), NULL, pIpe, sizeof(IP_ECHO_REPLY)+sizeof(acPingBuffer),100);if (dwStatus!=0) /the host is awaken ! TempObject-hostesi0=1; hostent * host=gethostbyaddr(const char*)(pip),4,AF_INET); if(host!=NULL) ClientHostName=host-h_name; CString temp; temp=inet_ntoa(*pip);n_item=TempObject-m_pcList.InsertItem(row_num,row,NULL); TempObject-m_pcList.SetItemText(n_item,0,temp); TempObject-m_pcList.SetItemText(n_item,1,ClientHostNme); TempObject-m_pcList.SetItemText(n_item,2,已开机); remoteaddr.sin_addr=*pip; int result=connect(DetectSock,(struct sockaddr *)&remoteaddr,sizeof(sockaddr); if(result=0) TempObject-hostesi1=1; TempObject-m_pcList.SetItemText(n_item,3,可聊天); else TempObject-hostesi1=0; TempObject-m_pcList.SetItemText(n_item,3,不可聊天); TempObject-m_pcList.SetItemText(n_item,4,传文件); row_num+;char finishscan40=Scan finished!;/扫描完毕。TempObject-GetDlgItem(IDC_STATIC_STATUS)-SetWindowText(finishscan);closesocket(DetectSock);/Close the detect socket!GlobalFree(pIpe);/ 关闭,回收资源信息发送模块详细设计信息发送事件是由用户在双击位于ListCtrl控件中的某一个用户列表的时候发生的,所以对ListCtrl的列表项双击事件添加事件响应函数如下:void CNetTestWithAPIDlg:OnDblclkPclist(NMHDR* pNMHDR, LRESULT* pResult) if(dlg.m_hWnd!=0) return; int nItem=-1; nItem=m_pcList.GetNextItem(nItem,LVNI_SELECTED); if(nItem=-1) return; CString strSelectedItem; strSelectedItem=m_pcList.GetItemText(nItem,0); CString temp=strSelectedItem; int n=0; int a=temp.Find(.); a=temp.Find(.,a+1); a=temp.Find(.,a+1); a=temp.GetLength()-a; CString temp2=temp.Right(a-1); n=atoi(temp2); if(hostesn1=1)/If the host cliked can be talked dlg.ClientHost.S_un.S_addr=inet_addr(temp); dlg.Create(IDD_SEND_DIALOG,this); dlg.ShowWindow(SW_SHOW); else AfxMessageBox(Theres no client in goal host!); *pResult = 0;信息接收模块详细设计信息接收由前面注册的网络事件被系统所触发,当void CNetTestWithAPIDlg:OnAccept(SOCKET CurSock) SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR);/为新的socket注册异步事件CurrentConn=accept(ServerSocket,(sockaddr*)&addrClient,&len); int n=addrClient.sin_addr.S_un.S_un_b.s_b4; dlg.ClientHost=addrClient.sin_addr;if(hostesn1=1)hostesn1=1; CString ClientIp=inet

温馨提示

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

评论

0/150

提交评论