基于UDP协议的聊天工具的设计_研究生课程论文.doc_第1页
基于UDP协议的聊天工具的设计_研究生课程论文.doc_第2页
基于UDP协议的聊天工具的设计_研究生课程论文.doc_第3页
基于UDP协议的聊天工具的设计_研究生课程论文.doc_第4页
基于UDP协议的聊天工具的设计_研究生课程论文.doc_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

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

文档简介

研究生课程论文课程名称 面向对象程序设计vc+ 学院 电子工程学院 专 业 电子与通信工程 基于udp协议的聊天工具的设计第1章 需求分析1.1 功能需求1 用户之间能够通过输入ip地址建立连接2 用户能够输入所需发送的信息,并能够在界面上发看到输入的信息3 用户之间可以相互通信1.2 应用平台需求安装有vs2008的操作系统,能够正常运行exe文件。1.3 界面的设计需求本程序利用udp协议来进行通信,因此可以简单地将发送端和接收端集成在同一个对话框界面上,并可以通过利用多线程技术以保证接受信息功能的顺畅。1.4 简单流程图建立连接聊天(发送、接受信息)结 束图1-1第2章 概要设计2.1 程序总体结构图 发送端 接收端创建套接字创建套接字 输入消息bind绑定创建接收线程 显示消息实现线程函数 发送消息 消息转换 接受消息 图2-12.2 发送端流程 发送消息 显示消息 输入消息创建套接字 图2-22.3 接收端流程 bind绑定创建套接字 消息转换 接受消息实现线程函数创建接收线程 图2-3第3章 详细设计3.1 界面设计图3-1说明:界面由一个对话框,两个编辑框,一个按钮和一个ip地址编辑框组成。其中接收数据栏中的编辑框可以显示发送的信息和接收到的信息,发送数据栏中编辑框则可以编辑发送信息,按回车键后即可发送信息。ip地址栏中可以输入需要连接的主机的ip地址。为了美观和方便,在添加按钮后,选中按钮控件的default和visialbe属性,将其设定为不可见,并通过回车能够实现按钮功能。3.2 多线程由于该聊天工具是将利用udp协议实现聊天功能,并将发送端和接收端(某种意义上也可以算是服务器和客户端)集成在一起,为了将发送功能和接受功能同时实现,需要用到多线程技术。因为在接收端接收数据时,如果数据没有来到,recvfrom函数会阻塞,从而导致程序暂停运行。所以,将接收数据的操作放置在一个单独的线程中完成。并给这个线程函数传递两个参数,一个是已创建的套接字,一个是对话框空间的句柄,这样,在该函数中,当接到数据后,可以将该数据传回给对话框,经过处理后显示在接受编辑框控件上。传递的结构体的代码如下:struct recvparam socket sock ; /已创建的套接字 hwnd hwnd; /对话框句柄;编写接受线程函数,并在一定情况下启动线程,具体代码请参阅附录。3.3 套接字因为本程序使用的是udp协议,并将接收端和发送端集成在一个面上,所以从理论上说,该界面即是服务器,又是客户端,而且基于udp协议的聊天工具的套接字中并不需要监听和接受的步骤,彼此是点对点式的平等,也正是因此,所以可以将服务器和客户端集成在一起。第四章 测试结果图4-1 第五章 总结这次课程设计对我来说是一个重大的挑战,因为从前没有学过c+,并对网络编程、套接字、多线程一无所知,所以遇到的困难很大。不过好在老师的指导和自己通过网络,图书馆等途径的查询,终于搞明白了其中的大部分内容,这次课程设计对我的vc是一个检验,更加是是对我学习能力的一个检验。在编写代码的过程中,所用到的技术基本上都能够从书上查到,并通过自己的揣摩能够编写,但是最后遇到了一个最大的问题,就是通过127.0.0.1的自网测试没有问题,但是在不同电脑相互通信的时候,往往套接字创建失败,这个问题一直困扰了我很长的时间,不管我怎么看代码都找不出其中的原因。后来通过网络相关论坛的帮助,我才明白,原来windows系统的防火墙对端口6000有限制,所以如果将套接字绑定在端口6000上,无法实现创建套接字,因此总是会不断地失败。只需要改为其他的端口,即可在不同电脑之间的相互通信。这算是我通过这次的课程设计所收获到的一个很大的知识点,也算是我的一个小礼物。这次课程设计是我和我的同学一起完成的,我们通过相互的讨论和研究,终于完成了这个聊天程序,我们的合作很愉快,也非常感谢老师的帮助,希望我们在以后的学习中能够迎接新的挑战。第六章 关键源程序afxsocketinit()是一个bool型函数,作用是初始化套接字,成功返回非0,不成功返回0。if(!afxsocketinit() /判断这个函数是否为0afxmessagebox(加载套接字库失败!); /为0会有提示return false;/返回false,关闭elseafxmessagebox(加载套接字库成功!);initsocket()函数用来初始化套接字,并和本地信息进行绑定。bool cchatdlg:initsocket()m_socket=socket(af_inet,sock_dgram,0); /*用变量m_socket接收创建的套接字。socket()是1个创建套接字的函数,如果创建不成功,返回invalid_socket。*/if(m_socket=invalid_socket) /*如果创建套接字失败,则返回false。*/messagebox(创建套接字失败!);return false;sockaddr_in addrsock; /*定义sockaddr_in类型结构体addrsock*/给结构体里的各个变量进行赋值。addrsock.sin_family=af_inet; /用网际域addrsock.sin_port=htons(5000); /*端口为5000,用htons函数转换成网络字节序*/获取主机ip地址,并赋值给结构体内变量。addrsock.sin_addr.s_un.s_addr=htonl(inaddr_any);/用bind函数将本地地址和建立的套接字进行绑定。int retval;retval=bind(m_socket,(sockaddr*)&addrsock,sizeof(sockaddr);/进行判断,如果绑定失败,关闭套接字,进行消息提示,返回false。if(socket_error=retval)closesocket(m_socket);messagebox(套接字与本地机地址绑定失败!);return false;else messagebox(套接字与本地机地址绑定成功!);return true;建立1个结构体recvparam,并用指针precvparam指向它。recvparam *precvparam=new recvparam;/*用new给指针分配1个动态空间*/precvparam-hwnd=m_hwnd; /给结构体变量赋初值,传递对话框句柄precvparam-sock=m_socket; /传递套接字用createthread创建一个新的线程,然后创建线程句柄hthread,用来接收createthread返回的句柄值。handle hthread=createthread(null,0,recvproc,(lpvoid)precvparam,0,null);closehandle(hthread); /*关闭新线程的句柄,递减线程内核对象的使用计数。*/新线程执行函数recvproc()dword winapi cchatdlg:recvproc(lpvoid lpparameter)/取出所传递的2个参数值,1个是套接字,1个是对话框句柄。socket sock=(recvparam*)lpparameter)-sock;hwnd hwnd=(recvparam*)lpparameter)-hwnd;sockaddr_in addrfrom;/*定义1个套接字地址结构变量,接收发送端的地址信息。*/int len=sizeof(sockaddr); /接收返回地址结构体的长度。char recvbuf100; /字符数组,用来接收到来的数据。char tempbuf100;/用来存放格式化后的数据。int retval;while(true) /做一个循环,让它不断接收数据retval=recvfrom(sock,recvbuf,100,0, /retval接收recvfrom的返回值(sockaddr*)&addrfrom,&len);if(retval=socket_error) /*如果返回socket_error,调用break语句,终止循环。*/break;/如果无错误,格式化recvbuf,将格式化后的数据放入tempbuf中。sprintf(tempbuf,%s说:%s,inet_ntoa(addrfrom.sin_addr),recvbuf); /*调用inet_ntoa,将发送端ip地址转换为点分十进制字符串*/将接收到的数据传递给对话框。:postmessage(hwnd,wm_recvdata,0,(lparam)tempbuf); return 0;对接收到的消息进行处理,使得能够按照一定格式输出。对于接收数据框来说,接收到的最新数据应该放到最顶端,以前的数据应该依次往下排列。void cchatdlg:onrecvdata(wparam wparam,lparam lparam)cstring str=(char*)lparam; /把lparam转换成字符型指针,然后赋给str。cstring strtemp; /接收旧的数据。getdlgitemtext(idc_edit_recv,strtemp);/从控件中得到文本。str+=rn; /让新的数据加1个换行。str+=strtemp; /再下一行加入先前的数据。setdlgitemtext(idc_edit_recv,str);/将数据放回接收的编辑框。发送函数void cchatdlg:onbtnsend() / todo: add your control notification handler code heredword dwip;/定义dword类型变量,用来接收控件的ip地址。(cipaddressctrl*)getdlgitem(idc_ipaddress1)-getaddress(dwip);/通过getdlgitem,得到控件的cwnd指针,再转换类型,得到dwip。sockaddr_in addrto; /定义地址结构体变量。addrto.sin_family=af_inet;addrto.sin_addr.s_un.s_addr=htonl(dwip);addrto.sin_port=htons(5000);cstring strsend;getdlgitemtext(idc_edit_send,strsend);/*得到编辑框的文本,传递给strsend。*/sendto(m_socket,strsend,strsend.getlength()+1,0,(sockaddr*)&addrto,sizeof(sockaddr);/发送数据。setdlgitemtext(idc_edit_send,);/*发送完后将编辑文本框设置为空。*/附录在chatapp类中的iniinstance(void)函数中添加一段代码: if(!afxsocketinit()afxmessagebox(加载套接字库失败!);return false;elseafxmessagebox(加载套接字库成功!); 以下是chatdlg.cpp中实现的代码:/ chatdlg.cpp : implementation file/#include stdafx.h#include chat.h#include chatdlg.h#ifdef _debug#define new debug_new#undef this_filestatic char this_file = _file_;#endif/ caboutdlg dialog used for app aboutclass caboutdlg : public cdialogpublic:caboutdlg();/ dialog data/afx_data(caboutdlg)enum idd = idd_aboutbox ;/afx_data/ classwizard generated virtual function overrides/afx_virtual(caboutdlg)protected:virtual void dodataexchange(cdataexchange* pdx); / ddx/ddv support/afx_virtual/ implementationprotected:/afx_msg(caboutdlg)/afx_msgdeclare_message_map();caboutdlg:caboutdlg() : cdialog(caboutdlg:idd)/afx_data_init(caboutdlg)/afx_data_initvoid caboutdlg:dodataexchange(cdataexchange* pdx)cdialog:dodataexchange(pdx);/afx_data_map(caboutdlg)/afx_data_mapbegin_message_map(caboutdlg, cdialog)/afx_msg_map(caboutdlg)/ no message handlers/afx_msg_mapend_message_map()/ cchatdlg dialogcchatdlg:cchatdlg(cwnd* pparent /*=null*/): cdialog(cchatdlg:idd, pparent)/afx_data_init(cchatdlg)/ note: the classwizard will add member initialization here/afx_data_init/ note that loadicon does not require a subsequent destroyicon in win32m_hicon = afxgetapp()-loadicon(idr_mainframe);void cchatdlg:dodataexchange(cdataexchange* pdx)cdialog:dodataexchange(pdx);/afx_data_map(cchatdlg)/ note: the classwizard will add ddx and ddv calls here/afx_data_mapbegin_message_map(cchatdlg, cdialog)/afx_msg_map(cchatdlg)on_wm_syscommand()on_wm_paint()on_wm_querydragicon()on_bn_clicked(idc_btn_send, onbtnsend)/afx_msg_mapon_message(wm_recvdata,onrecvdata)end_message_map()/ cchatdlg message handlersbool cchatdlg:oninitdialog()cdialog:oninitdialog();/ add about. menu item to system menu./ idm_aboutbox must be in the system command range.assert(idm_aboutbox & 0xfff0) = idm_aboutbox);assert(idm_aboutbox appendmenu(mf_separator);psysmenu-appendmenu(mf_string, idm_aboutbox, straboutmenu);/ set the icon for this dialog. the framework does this automatically/ when the applications main window is not a dialogseticon(m_hicon, true);/ set big iconseticon(m_hicon, false);/ set small icon/ todo: add extra initialization hereinitsocket();recvparam *precvparam=new recvparam;precvparam-hwnd=m_hwnd;precvparam-sock=m_socket;handle hthread=createthread(null,0,recvproc,(lpvoid)precvparam,0,null);closehandle(hthread);this-setwindowtext(chatwindow);return true; / return true unless you set the focus to a controlvoid cchatdlg:onsyscommand(uint nid, lparam lparam)if (nid & 0xfff0) = idm_aboutbox)caboutdlg dlgabout;dlgabout.domodal();elsecdialog:onsyscommand(nid, lparam);/ if you add a minimize button to your dialog, you will need the code below/ to draw the icon. for mfc applications using the document/view model,/ this is automatically done for you by the framework.void cchatdlg:onpaint() if (isiconic()cpaintdc dc(this); / device context for paintingsendmessage(wm_iconerasebkgnd, (wparam) dc.getsafehdc(), 0);/ center icon in client rectangleint cxicon = getsystemmetrics(sm_cxicon);int cyicon = getsystemmetrics(sm_cyicon);crect rect;getclientrect(&rect);int x = (rect.width() - cxicon + 1) / 2;int y = (rect.height() - cyicon + 1) / 2;/ draw the icondc.drawicon(x, y, m_hicon);elsecdialog:onpaint();/ the system calls this to obtain the cursor to display while the user drags/ the minimized window.hcursor cchatdlg:onquerydragicon()return (hcursor) m_hicon;bool cchatdlg:initsocket()m_socket=socket(af_inet,sock_dgram,0); /创建套接字if(m_socket=invalid_socket)messagebox(创建套接字失败!);return false; /初始化套接字sockaddr_in addrsock;addrsock.sin_family=af_inet;addrsock.sin_port=htons(5000);addrsock.sin_addr.s_un.s_addr=htonl(inaddr_any);int retval;retval=bind(m_socket,(sockaddr*)&addrsock,sizeof(sockaddr);if(socket_error=retval)closesocket(m_socket);messagebox(套接字与本地机地址绑定失败!);return false;else messagebox(套接字与本地机地址绑定成功!);return true;/接收线程函数dword winapi cchatdlg:recvproc(lpvoid lpparameter)socket sock=(recvparam*)lpparameter)-sock;hwnd hwnd=(recvparam*)lpparameter)-hwnd;sockad

温馨提示

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

评论

0/150

提交评论