版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、基于基于 UDPUDP 的的 P2PP2P 模式的聊天程序模式的聊天程序 一、一、 课题内容和要求课题内容和要求 使用 UDP 协议编写聊天软件,使得客户端之间可以自由地进行键盘聊天。 【程序的具体要求】 1)以图形界面运行, 提供聊天内容输入界面和收到的文字聊天内容。 2)允许客户选择不同的其他客户方(peer)进行聊天,假定已知对方的 IP 地址。 二、二、需求分析需求分析 本次试验需要使用 UDP 协议的 P2P 模式,所以在试验之前应该对其进行一定了解。 UDP 是 User Datagram Protocol 的简称, 中文名是用户数据包协议,是 OSI 参考 模型中一种无连接的传输
2、层协议,提供面向事务的简单不可靠信息传送服务。UDP 是 ISO 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。UDP 协议基本上是 IP 协议与上层协议的接口。UDP 协议适用端口分辨运行在同一台设备上的 多个应用程序。UDP 协议的全称是用户数据报协议,在网络中它与 TCP 协议一样用于处理 UDP 数据包。在 OSI 模型中,在第四层传输层,处于 IP 协议的上一层。UDP 有不提 供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无 法得知其是否安全完整到达的。 UDP 用来支持那些需要在计算机之间传输数据的网络应 用。包括网络视频会议
3、系统在内的众多的客户/服务器模式的网络应用都需要使用 UDP 协 议。UDP 协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所 掩盖,但是即使是在今天,UDP 仍然不失为一项非常实用和可行的网络传输层协议。与所 熟知的 TCP(传输控制协议)协议一样,UDP 协议直接位于 IP(网际协议)协议的顶层。 根据 OSI(开放系统互连)参考模型,UDP 和 TCP 都属于传输层协议。UDP 协议的主要作 用是将网络数据流量压缩成数据报的形式。一个典型的数据报就是一个二进制数据的传 输单位。每一个数据报的前 8 个字节用来包含报头信息,剩余字节则用来包含具体的传 输数据。 P2P
4、 是英文 Peer-to-Peer(对等)的简称,又被称为“点对点” 。 “对等”技术,是 一种网络新技术,依赖网络中参与者的计算能力和带宽,而不是把依赖都聚集在较少的 几台服务器上。P2P 还是英文 Point to Point (点对点)的简称。它是下载术语,意思 是在你自己下载的同时,自己的电脑还要继续做主机上传,这种下载方式,人越多速度 越快但缺点是对硬盘损伤比较大(在写的同时还要读) ,还有对内存占用较多,影响整机 速度。点对点技术(peer-to-peer, 简称 P2P)又称对等互联网络技术,是一种网络新 技术,依赖网络中参与者的计算能力和带宽,而不是把依赖都聚集在较少的几台服务
5、器 上。但 P2P 并非纯粹的点对点技术,实为解作群对群(Peer-to-Peer)。在虚拟私人网络 VPN (Virtual Private Network)中,也有 P2P 这个名称,它才是真正解作点对(Point- to-Point)。对等联网:1、是只读的网络的终结(Peer-to-peer is the end of the read-only Web) 。2、使你重新参与互联网(Peer-to-peer allows you to participate in the Internet again)3、使网络远离电视(Peer-to-peer steering the Intern
6、et away from TV)如上文所言,P2P 不是一个新思想,从某些角度看它甚至是整个最初创建 互联网的最基本的思想。 本次编程用的工具是 VC6.0,因为需要做图形化界面,所以又自学了 MFC。 这个试验的主要部分在,使用 UDP 协议上面,制作图形界面,创建套接字等方面。 运行以后程序会出现很多的.h 和.cpp 的文件,框架和主代码写于在 UDPChatDlg.cpp 文 件和 UDPSock.cpp 文件中。在做图形界面的时候,我打算做一个对话框,一个输入框, 两个 IP 地址栏,两个端口栏,一个发送键,一个关闭键,一个设置 IP 地址键。每一个 界面都对应一个类来实现其功能。
7、在 UDPChatDlg.cpp 中,BOOL CUDPChatDlg:OnInitDialog()中,实现了很多的功能, 创建调用套接字、获得主机 IP 和端口号,以及对方的的 IP 初始值。void CUDPChatDlg:OnBtnConn()中,实现了设置键的功能。void CUDPChatDlg:OnBtnSend() 中,是实现了发送的功能,读取输入框的信息并点击响应,使其能够显示在对话框,而 且会对另外类的功能进行调用。void CUDPChatDlg:SendMsg()是自己添加的功能,使其 图形化界面比较完善,可以显示发送方还有接收方。void CUDPChatDlg:OnB
8、tnFont()也 是添加的一项功能,用来调节字体大小颜色等。 在 UDPSock.cpp 中,void CUDPSock:OnReceive()这个需要说明,是为了接收信息 的,其中调用了自己定义的结构,用于灵活分配空间,在试验过程中,在这个地方也出 现了问题。 三、三、概要设计概要设计 这次试验程序的代码,我将程序的头文件和源文件分开些的。另外要说明的是,试 验代码是用 CSocket 写的,CSocket 是多线程的。 头文件中,Protocol.h 文件是我自己写的代码,用于实现动态的获得消息,可以是 程序在运行获得消息的时候,首先获得报头,然后再去获得消息的数据包,这样可以分 配合适
9、的内存,不要分配固定的内存。 UDPChat.h 文件里面用到了 CWinApp,MFC 中的主应用程序类封装用于 Windows 操 作系统的应用程序的初始化、运行和终止。基于框架生成的应用程序必须有且仅有一个 从 CWinApp 派生的类的对象。在创建窗口之前先构造该对象。 UDPChatDlg.h 文件中,CUDPSock m_sockUDP;来使用 UDP 套接字,CHARFORMAT m_cfDefault;来控制默认字体,void SendMsg(BOOL bSelf, CString strName, CTime 显示消息的函数。 在 UDPSock.h 中,主要是对 CUDPS
10、ocket 进行声明调用等。 源文件中,很多都是框架的代码,在此可以忽略。对一些功能函数和模块进行说明。 StdAfx.cpp 文件中,用于调用程序所有的主要头文件,一定不能省略。 对于 UDPChat.cpp 文件,其实不用进行过多的说明,但是在程序中,一定要注意 AfxInitRichEdit();初始化 RichEdit,否则会出现一些问题。 接下来是 UDPChatDlg.cpp 源文件,这是程序的主要代码,很多的框架代码以及功能 函数都在这个地方。1、BOOL CUDPChatDlg:OnInitDialog()中,CString str, strSockName, strPort;
11、是为了获取主机 IP。m_sockUDP.Close();是为了创建 UDP 套接字, 在程序中,我对其进行了封装,然后调用。m_sockUDP.GetSockName(strSockName, uiPort);可以用来获取本机的端口,因为题目说在已知对方 IP 的条件下,所以当然要获 得 IP,虽然也可以手动查询本机 IP,但是这样的话方便了很多。 2、CUDPChatDlg:OnBtnConn()中,实现了设置键的功能,就是在输入对方 IP 和端口号 以后,进行连接响应。3、void CUDPChatDlg:OnBtnSend()中,是进行主要工作,调用 一些功能以及响应发送的命令。m_c
12、trlRichSend.SetFocus();是用于获取字符串,清空 发送框。T_MSG_STRUCT tMsgHdr;用于发送数据包准备工作。lstrcpy(lpMsg, str.GetBuffer(0);str.ReleaseBuffer();用来复制消息内容。 m_ctrlRichSend.GetDefaultCharFormat(tMsgHdr.cf); 用来设置字体。 tMsgHdr.timeSent = CTime:GetCurrentTime();用于设置发送时间。tMsgHdr.uiMsgLen = str.GetLength();用于设置消息长度,_tcscpy(tMsgHd
13、r.szName, m_strSelfName); 用于设置发送者名称,DWORD dwIPAddress; 等代码 用于获取目的主机的 IP 和端口。还 有一些功能就不一一介绍了,在下面的程序都有给出注释。4、最后 void CUDPChatDlg:OnBtnFont()中,是自己添加的功能,用于实现修改字体的大小,颜色, 字体等功能。 最后是 UDPSock.cpp 源文件,void CUDPSock:OnReceive(int nErrorCode)是这个 文件的主要部分,实现了先接收消息头部、然后接收消息,并显示别人发送过来的消息。 其实在抓取消息的时候,我并没有用线程,而是像一个死循
14、环一样,不断的抓取信息, 知道用户点击发送才开始响应,并获取消息和显示。 四、四、详细设计详细设计 因为程序代码含有很多框架的代码,都是系统自带的,所以我找一些重要的自己写 的代码附在此部分。 1、UDPChatDlg.cpp 文件中的代码是主要代码,所以全部反映出来: #include stdafx.h #include UDPChat.h #include UDPChatDlg.h #include Protocol.h #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE = _FILE_;
15、#endif / / CAboutDlg dialog used for App About class CAboutDlg : public CDialog public: 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*
16、 pDX); / DDX/DDV support /AFX_VIRTUAL / Implementation protected: /AFX_MSG(CAboutDlg) /AFX_MSG DECLARE_MESSAGE_MAP() ; CAboutDlg:CAboutDlg() : CDialog(CAboutDlg:IDD) /AFX_DATA_INIT(CAboutDlg) /AFX_DATA_INIT void CAboutDlg:DoDataExchange(CDataExchange* pDX) CDialog:DoDataExchange(pDX); /AFX_DATA_MAP(
17、CAboutDlg) /AFX_DATA_MAP BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) /AFX_MSG_MAP(CAboutDlg) / No message handlers /AFX_MSG_MAP END_MESSAGE_MAP() / / CUDPChatDlg dialog CUDPChatDlg:CUDPChatDlg(CWnd* pParent /*=NULL*/) : CDialog(CUDPChatDlg:IDD, pParent) /AFX_DATA_INIT(CUDPChatDlg) / NOTE: the ClassWizard
18、will add member initialization here /AFX_DATA_INIT / Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME); void CUDPChatDlg:DoDataExchange(CDataExchange* pDX) CDialog:DoDataExchange(pDX); /AFX_DATA_MAP(CUDPChatDlg) DDX_Control(pDX, IDC_R
19、ICHEDIT_BOX, m_ctrlRichBox); DDX_Control(pDX, IDC_RICHEDIT_SEND, m_ctrlRichSend); /AFX_DATA_MAP BEGIN_MESSAGE_MAP(CUDPChatDlg, CDialog) /AFX_MSG_MAP(CUDPChatDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_DESTROY() ON_BN_CLICKED(IDC_BTN_CONN, OnBtnConn) ON_BN_CLICKED(IDC_BTN_SEND,
20、OnBtnSend) ON_BN_CLICKED(IDC_BTN_CLOSE, OnBtnClose) ON_BN_CLICKED(IDC_BTN_FONT, OnBtnFont) /AFX_MSG_MAP END_MESSAGE_MAP() / / CUDPChatDlg message handlers BOOL CUDPChatDlg:OnInitDialog() CDialog:OnInitDialog(); / Add About. menu item to system menu. / IDM_ABOUTBOX must be in the system command range
21、. ASSERT(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 dialog SetIcon(m_hIcon, TRUE);/ Set big icon SetIcon(m_hI
22、con, FALSE);/ Set small icon / TODO: Add extra initialization here / WSADATA wsaData; TCHAR name155; TCHAR *ip; PHOSTENT hostinfo; / 获取本机 IP 地址 CString str, strSockName, strPort; UINT uiPort; if (WSAStartup(MAKEWORD(2, 0), WSACleanup(); str.Format(_T(%s), ip); GetDlgItem(IDC_EDIT_ADDRESS_LOCAL)-SetW
23、indowText(str); / 创建 UDP 套接字 m_sockUDP.Close(); if (!m_sockUDP.Create(0, SOCK_DGRAM, NULL) MessageBox(_T(连接服务器失败!), _T(提示), MB_OK | MB_ICONINFORMATION); return FALSE; / 获取本机端口 m_sockUDP.GetSockName(strSockName, uiPort); strPort.Format(_T(%u), uiPort); GetDlgItem(IDC_EDIT_LOCAL_PORT)-SetWindowText(st
24、rPort); / 初始化名字 m_strSelfName.Format(_T(), str, uiPort); / 初始值 (CIPAddressCtrl *)GetDlgItem(IDC_IPADDRESS_REMOTE)-SetAddress(127, 0, 0, 1); GetDlgItem(IDC_EDIT_REMOTE_PORT)-SetWindowText(_T(0); / 默认字体 ZeroMemory( m_cfDefault.yHeight = 180; m_cfDefault.cbSize = sizeof(CHARFORMAT); m_cfDefault.dwMask
25、|= CFM_SIZE; m_cfDefault.dwMask |= CFM_FACE; m_cfDefault.dwMask |= CFM_BOLD; m_cfDefault.dwMask |= CFM_ITALIC; m_cfDefault.dwMask |= CFM_OFFSET; m_cfDefault.dwMask |= CFM_STRIKEOUT; m_cfDefault.dwMask |= CFM_UNDERLINE; m_cfDefault.dwEffects m_cfDefault.dwEffects m_cfDefault.dwEffects m_cfDefault.dwE
26、ffects m_cfDefault.yOffset = 0; lstrcpy(m_cfDefault.szFaceName, _T(宋体); / return TRUE; / return TRUE unless you set the focus to a control void CUDPChatDlg:OnSysCommand(UINT nID, LPARAM lParam) if (nID dlgAbout.DoModal(); else CDialog:OnSysCommand(nID, lParam); / If you add a minimize button to your
27、 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 CUDPChatDlg:OnPaint() if (IsIconic() CPaintDC dc(this); / device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.G
28、etSafeHdc(), 0); / Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect( int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; / Draw the icon dc.DrawIcon(x, y, m_hIcon); else CDialo
29、g:OnPaint(); / The system calls this to obtain the cursor to display while the user drags / the minimized window. HCURSOR CUDPChatDlg:OnQueryDragIcon() return (HCURSOR) m_hIcon; void CUDPChatDlg:OnDestroy() CDialog:OnDestroy(); / TODO: Add your message handler code here / m_sockUDP.Close(); / void C
30、UDPChatDlg:OnBtnConn() / TODO: Add your control notification handler code here / UpdateData(FALSE); MessageBox(_T(设置成功!), _T(提示), MB_OK | MB_ICONINFORMATION); / void CUDPChatDlg:OnBtnSend() / TODO: Add your control notification handler code here / CString str; INT iLen = m_ctrlRichSend.GetWindowText
31、Length(); / 条件验证 if (iLen = 0) MessageBox(_T(发送内容不能为空,n 请重新输入!), _T(提示), MB_OK | MB_ICONINFORMATION); return; if (iLen = 1000) MessageBox(_T(您所发的信息太长。), _T(请截短信息), MB_OK | MB_ICONINFORMATION); return; / 获取字符串,清空发送框 m_ctrlRichSend.SetFocus(); m_ctrlRichSend.SetSel(0, iLen); str = m_ctrlRichSend.GetSe
32、lText(); m_ctrlRichSend.ReplaceSel(_T(); / 发送数据包准备工作 T_MSG_STRUCT tMsgHdr; LPTSTR lpMsg = new TCHARstr.GetLength() + 1; / 复制消息内容 lstrcpy(lpMsg, str.GetBuffer(0); str.ReleaseBuffer(); / 设置字体 m_ctrlRichSend.GetDefaultCharFormat(tMsgHdr.cf); / 设置发送时间 tMsgHdr.timeSent = CTime:GetCurrentTime(); / 设置消息长度
33、tMsgHdr.uiMsgLen = str.GetLength(); / 设置发送者名称 _tcscpy(tMsgHdr.szName, m_strSelfName); / 获取目的主机的 IP 和端口 DWORD dwIPAddress; (CIPAddressCtrl *)GetDlgItem(IDC_IPADDRESS_REMOTE)-GetAddress(dwIPAddress); CString strPort; GetDlgItem(IDC_EDIT_REMOTE_PORT)-GetWindowText(strPort); / 设置 SOCKADDR_IN SOCKADDR_IN
34、 clientaddr; clientaddr.sin_addr.S_un.S_addr = htonl(dwIPAddress); clientaddr.sin_family = AF_INET; clientaddr.sin_port = htons(atoi(strPort); / 发送数据包 m_sockUDP.SendTo( m_sockUDP.SendTo(lpMsg, (str.GetLength() + 1) * sizeof(TCHAR), (SOCKADDR *) / 目的主机的名称 CString strRemoteName; strRemoteName.Format(_
35、T(), inet_ntoa(clientaddr.sin_addr), strPort); / 显示到聊天框中 SendMsg(TRUE, strRemoteName, tMsgHdr.timeSent, lpMsg, tMsgHdr.cf); / 焦点回到发送框 m_ctrlRichSend.SetFocus(); / 释放空间 SAFEDELETEA(lpMsg); / / /* / Method: SendMsg / FullName: CUDPChatDlg:SendMsg / Access: protected / Returns: void / Qualifier: / Para
36、meter: BOOL bSelf 是否是自己发送的 / Parameter: CString strName 要显示的发送、目的主机的名字 / Parameter: CTime m_ctrlRichBox.AddText(_T(rn), m_cfDefault); str.Format(_T(%s %s %s 说:rn), time.Format(_T(%H:%M:%S), bSelf ? _T(你对) : strName, bSelf ? strName : _T(对你); if (bSelf) / 显示自己发送的标题 m_ctrlRichBox.AddTitle(str, m_cfDef
37、ault, RGB(0, 128, 64); else / 显示别人发送的标题 m_ctrlRichBox.AddTitle(str, m_cfDefault); str.Format(_T(%s), strMsg); / 显示消息 m_ctrlRichBox.AddText(str, cf); / 任务栏按钮闪烁效果 if (!bSelf / void CUDPChatDlg:OnBtnClose() / TODO: Add your control notification handler code here OnCancel(); void CUDPChatDlg:OnBtnFont()
38、 / TODO: Add your control notification handler code here / / CHARFORMAT cf; LOGFONT lf; memset( memset( m_ctrlRichSend.GetDefaultCharFormat(cf); /得到相关字体属 BOOL bIsBold = cf.dwEffects BOOL bIsItalic = cf.dwEffects BOOL bIsUnderline = cf.dwEffects BOOL bIsStrickout = cf.dwEffects /设置属性 lf.lfCharSet = c
39、f.bCharSet; lf.lfHeight = cf.yHeight / 15; lf.lfPitchAndFamily = cf.bPitchAndFamily; lf.lfItalic = bIsItalic; lf.lfWeight = (bIsBold ? FW_BOLD : FW_NORMAL); lf.lfUnderline = bIsUnderline; lf.lfStrikeOut = bIsStrickout; lstrcpy(lf.lfFaceName, cf.szFaceName); CFontDialog dlg( dlg.m_cf.rgbColors = cf.c
40、rTextColor; if (dlg.DoModal() = IDOK) dlg.GetCharFormat(cf);/获得所选字体的属性 m_ctrlRichSend.SetWordCharFormat(cf); m_ctrlRichSend.SetDefaultCharFormat(cf); / BOOL CUDPChatDlg:PreTranslateMessage(MSG* pMsg) / TODO: Add your specialized code here and/or call the base class / / 屏蔽 ENTER 和 ESC if (pMsg-message = WM_KEYDOWN / return CDialog:PreTranslateMessage(pMsg); 2、UDPSock.cpp 文件中的代码是自己编写用于接收信息的,所以把 OnReceive() 类附在这里。
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030年卫生洁具零售行业跨境出海战略分析研究报告
- 2025-2030年中国酱油原料基地行业前景趋势预测及发展战略咨询报告
- 2025-2030年私募股权基金份额转让平台行业深度调研及发展战略咨询报告
- 2025-2030年电动灌肠机企业制定与实施新质生产力战略分析研究报告
- 2025-2030年人工智能行业数字营销策略分析研究报告
- 连续配筋复合路面施工方案
- 2025年药品生产质量管理规范培训试题及答案
- 2026年兰州兰石集团有限公司校园招聘(30+人)笔试备考题库及答案详解
- 2026湖南邵阳工业职业技术学院选调3人笔试备考试题及答案详解
- 2026新疆水发建设集团有限公司招聘12人笔试备考题库及答案详解
- 2026年宝鸡市辛家山林业局、宝鸡市马头滩林业局招聘(12人)考试参考题库及答案解析
- 江西省南昌市2026届高三年级四月第二次模拟语文试卷(含答案)
- 2026广岩国际投资有限责任公司招聘14人备考题库附答案详解(综合卷)
- XJJ013-2012 新疆维吾尔自治区城市规划管理技术规定
- 2026年非遗保护中心招聘考试面试题及参考答案
- 智慧树 创造性思维与创新方法 章节测试答案
- 6.3 社会主义市场经济体制(教学设计) 2025-2026学年统编版道德与法治八年级下册
- 2025-2026中国市场IP商业化价值研究报告
- 2026年创新药挂网采购随时申报自主定价直接挂网流程
- 2026年商丘职业技术学院单招职业技能测试题库及答案详解(名师系列)
- 机械厂卫生管理制度
评论
0/150
提交评论