前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UDP即时通信

UDP即时通信

作者头像
沁溪源
发布2020-09-03 10:58:03
1.4K0
发布2020-09-03 10:58:03
举报
文章被收录于专栏:沁溪源

编写一个基于某种I/O方法的UDP应用程序:能够实现模拟C/S模型的通信方 式,接收方负责信息的接收,并能够返回给客户端相应的消息;发送方负

责向接收方发送信息。

1.完成实验要求UDP之间通信;

2.实现模拟C/S模型的通信方式,接收方负责信息的接收,并能够返回给客户端相应的消息;发送方负责向接收方发送信息。

3.完成数据的传送信息;

完成大致步骤:

1.首先创建一个先项目工程,特别注意是在高级选项卡中选择套接字,然后将工程名为UDProcsComm;项目完成创建完成之后,选择资源视图,然后在对话框中开始设置界面格式:首先将界面设计区的“确定”修改成“启动”,在属性选项卡中选择caption属性,“取消”按钮修改成“退出”;在工具箱中,选择列表框、IP地址,编辑框,按钮,静态编辑框以及组合框等控件,然后选择这些控件,以及在属性中选择ID选项,将控件的ID修改,同时右击控件,选择添加事件处理程序,依次在主对话框中的cpp文件中添加 事件处理程序,实现这些控件的功能需求; 2.编写代码实现: 首先在UDProcsCommDlg.h头文件中定义变量和声明一些方法,用于连接客户端的请求,以及SOCKET的结构,收发消息的结构体;然后在UDProcsCommDlg.cpp文件中完善主对话框的构造函数,将端口等控件的初始值设置成0;同时在主对话框中的初始化函数(OnInitDialog)将界面中的一些控件设置成false; 设置“启动”按钮的事件处理程序:首先添加OnOK函数,在函数中首先将界面用updateData()函数更新一下,然后利用函数判断端口号以及IP是否为空,同时给出相应的提示语句;在函数中首先初始化和绑定IP地址,调用Windows SocketDLL 进行初始化,然后创建本机进程的Socket,建立无连接之间的通信;然后在实现获取IP地址的编程语句,编写语句绑定与设置相同的端口号,自定义消息产生相应传递给窗口的消息,然后调用Enablewindow()函数,设置界面上的控件信息,; 在“stdafx.h”的头文件中,定义宏,以及结构体msg变量;在对话框中cpp文件中定义消息宏映射; 在主对话框中添加OnReadClose()函数中自定义关闭和缓冲区的消息;同时,添加“停止”,“发送”按钮的事件处理函数,在OnStop函数时将界面上的控件设置成false和true;当程序运行停止时,将Socket清空;在OnSend函数中,获取IP地址的相关信息,将数据进行发送;

1.在项目中的资视图中,选择dialog,设置页面布局,在界面上添加一些控件,IP地址、编辑框、按钮等控件,同时在右击各个控件选择添加变量,将控件和变量关联在一起,同时为控件添加事件处理函数;

1.完成程序编写后,启动运行调试程序,首先设置本机IP地址为127.0.0.1,端口号设置为1035,然后点击启动,同时在信息列表框中提示启动成功等信息;

源代码:

// UDProcsComm.cpp : 定义应用程序的类行为。 // #include "stdafx.h" #include "UDProcsComm.h" #include "UDProcsCommDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CUDProcsCommApp BEGIN_MESSAGE_MAP(CUDProcsCommApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP() // CUDProcsCommApp 构造 CUDProcsCommApp::CUDProcsCommApp() { // 支持重新启动管理器 m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; // TODO: 在此处添加构造代码, // 将所有重要的初始化放置在 InitInstance 中 } // 唯一的一个 CUDProcsCommApp 对象 CUDProcsCommApp theApp; // CUDProcsCommApp 初始化 BOOL CUDProcsCommApp::InitInstance() { // 如果一个运行在 Windows XP 上的应用程序清单指定要 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式, //则需要 InitCommonControlsEx()。否则,将无法创建窗口。 INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // 将它设置为包括所有要在应用程序中使用的 // 公共控件类。 InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); if (!AfxSocketInit()) { AfxMessageBox(IDP_SOCKETS_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); // 创建 shell 管理器,以防对话框包含 // 任何 shell 树视图控件或 shell 列表视图控件。 CShellManager *pShellManager = new CShellManager; // 标准初始化 // 如果未使用这些功能并希望减小 // 最终可执行文件的大小,则应移除下列 // 不需要的特定初始化例程 // 更改用于存储设置的注册表项 // TODO: 应适当修改该字符串, // 例如修改为公司或组织名 SetRegistryKey(_T("应用程序向导生成的本地应用程序")); CUDProcsCommDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: 在此放置处理何时用 // “确定”来关闭对话框的代码 } else if (nResponse == IDCANCEL) { // TODO: 在此放置处理何时用 // “取消”来关闭对话框的代码 } // 删除上面创建的 shell 管理器。 if (pShellManager != NULL) { delete pShellManager; } // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序, // 而不是启动应用程序的消息泵。 return FALSE; } // UDProcsCommDlg.cpp : 实现文件 // #include "stdafx.h" #include "UDProcsComm.h" #include "UDProcsCommDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) //ADD END_MESSAGE_MAP() //ADD // CUDProcsCommDlg 对话框 CUDProcsCommDlg::CUDProcsCommDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CUDProcsCommDlg::IDD, pParent) , LocalPort(_T("")) , DestPort(_T("")) , str(_T("")) { str=_T(""); m_sport=0; m_dport=0; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); IsTrue=FALSE; Client=INVALID_SOCKET; } void CUDProcsCommDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_IPLOCAL, IPLocal); DDX_Control(pDX, IDC_PORTLOCAL, PortLocal); DDX_Text(pDX, IDC_PORTLOCAL, LocalPort); DDX_Control(pDX, IDOK, m_Start); DDX_Control(pDX, IDC_STOP, m_Stop); DDX_Control(pDX, IDC_IPDEST, IPDest); DDX_Control(pDX, IDC_PORTDEST, PortDest); DDX_Text(pDX, IDC_PORTDEST, DestPort); DDX_Control(pDX, IDC_EDITWORDS, m_EditWords); DDX_Text(pDX, IDC_EDITWORDS, str); DDX_Control(pDX, IDC_SEND, m_Send); DDX_Control(pDX, IDC_LIST, list); DDX_Control(pDX, IDCANCEL, m_Exit); } BEGIN_MESSAGE_MAP(CUDProcsCommDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_STOP, &CUDProcsCommDlg::OnBnClickedStop) ON_BN_CLICKED(IDC_SEND, &CUDProcsCommDlg::OnBnClickedSend) //ADD ON_MESSAGE(WM_CLIENT_READCLOSE,OnReadClose) END_MESSAGE_MAP() // CUDProcsCommDlg 消息处理程序 BOOL CUDProcsCommDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 //ADD IPLocal.SetFocus(); list.EnableWindow(false); m_Stop.EnableWindow(false); IPDest.EnableWindow(false); PortDest.EnableWindow(false); m_EditWords.EnableWindow(false); m_Send.EnableWindow(false); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CUDProcsCommDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CUDProcsCommDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int 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; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CUDProcsCommDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CUDProcsCommDlg::OnOK() { // TODO: 在此添加专用代码和/或调用基类 //ADD UpdateData(); if(IPLocal.IsBlank()) { AfxMessageBox("请设置IP地址!"); return ; } if(LocalPort.IsEmpty()) { AfxMessageBox("请设置端口号!"); return ; } WSADATA wsaData; int iErrorCode; if(WSAStartup(MAKEWORD(2,1),&wsaData)) { list.AddString("Winsock无法初始化!"); WSACleanup(); return ; } list.AddString("开始创建Socket..."); ServerSocket=socket(PF_INET,SOCK_DGRAM,0); if(ServerSocket==INVALID_SOCKET) { list.AddString("创建Socket失败!"); return ; } BYTE nFild[4]; CString sIP; IPLocal.GetAddress(nFild[0],nFild[1],nFild[2],nFild[3]); sIP.Format("%d.%d.%d.%d",nFild[0],nFild[1],nFild[2],nFild[3]); m_sockServerAddr.sin_family=AF_INET; m_sockServerAddr.sin_addr.s_addr=inet_addr(sIP); m_sockServerAddr.sin_port=htons(atoi(LocalPort)); socklen=sizeof(m_sockServerAddr); if(bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr))==SOCKET_ERROR) { list.AddString("绑定失败!"); return ; } iErrorCode=WSAAsyncSelect(ServerSocket,m_hWnd,WM_CLIENT_READCLOSE,FD_READ); if(iErrorCode==SOCKET_ERROR) { list.AddString("WSAAsyncSelect设定失败!--用户连接请求的消息"); return ; } list.AddString("本机进程启动成功!"); list.AddString("地址"+sIP+" 端口"+LocalPort); this->SetWindowTextA("本机应用进程("+sIP+":"+LocalPort+")-UDProcsComm"); IPLocal.EnableWindow(false); PortLocal.EnableWindow(false); m_Start.EnableWindow(false); m_Stop.EnableWindow(true); IPDest.EnableWindow(true); IPDest.SetFocus(); PortDest.EnableWindow(true); m_EditWords.EnableWindow(true); m_Send.EnableWindow(true); list.EnableWindow(true); m_Exit.EnableWindow(false); return ; CDialogEx::OnOK(); } LRESULT CUDProcsCommDlg::OnReadClose(WPARAM wParam,LPARAM lParam) { CString str; switch(WSAGETSELECTEVENT(lParam)) { case FD_READ: if(recvfrom(ServerSocket,(char *)&msg,sizeof(msg),0,(LPSOCKADDR)&m_sockServerAddr,(int *)&socklen)==SOCKET_ERROR) { list.AddString("发送失败!对方主机或应用进程没有启动"); return 0; } str.Format("%s",msg.msg); list.AddString(str); break; } return 0L; } void CUDProcsCommDlg::OnBnClickedStop() { // TODO: 在此添加控件通知处理程序代码 list.AddString("正在关闭Socket..."); closesocket(ServerSocket); WSACleanup(); list.AddString("本机进程停止运行!"); m_Start.EnableWindow(false); m_Stop.EnableWindow(false); list.EnableWindow(false); IPLocal.SetFocus(); IPDest.EnableWindow(false); PortDest.EnableWindow(false); m_EditWords.EnableWindow(false); m_Send.EnableWindow(false); m_Exit.EnableWindow(true); } void CUDProcsCommDlg::OnBnClickedSend() { // TODO: 在此添加控件通知处理程序代码 UpdateData(); if(IPDest.IsBlank()) { AfxMessageBox("请指定目标进程所在主机的IP地址!"); return ; } if(DestPort.IsEmpty()) { AfxMessageBox("请指定目标进程的端口号!"); return ; } BYTE nFild[4]; CString sIP; IPLocal.GetAddress(nFild[0],nFild[1],nFild[2],nFild[3]); sIP.Format("%d.%d.%d.%d",nFild[0],nFild[1],nFild[2],nFild[3]); m_sockAddrto.sin_family=AF_INET; m_sockAddrto.sin_addr.s_addr=inet_addr(sIP); m_sockAddrto.sin_port=htons(atoi(DestPort)); if(str.IsEmpty()) { AfxMessageBox("发送的消息不能为空!"); return ; } strcpy(msg.msg,(LPCTSTR)str); msg.i=0; if(sendto(ServerSocket,(char *)&msg,sizeof(msg),0,(LPSOCKADDR)&m_sockAddrto,sizeof(m_sockAddrto))==SOCKET_ERROR) { list.AddString("发送消息失败!"); } str.Empty(); UpdateData(FALSE); } // UDProcsCommDlg.h : 头文件 // #pragma once #include "afxcmn.h" #include "afxwin.h" // CUDProcsCommDlg 对话框 class CUDProcsCommDlg : public CDialogEx { // 构造 public: CUDProcsCommDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_UDPROCSCOMM_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: CIPAddressCtrl IPLocal; CEdit PortLocal; CString LocalPort; CButton m_Start; CButton m_Stop; CIPAddressCtrl IPDest; CEdit PortDest; CString DestPort; CEdit m_EditWords; CString str; CButton m_Send; CListBox list; CButton m_Exit; //ADD SOCKET Client; SOCKET ServerSocket; SOCKADDR_IN m_sockServerAddr; SOCKADDR_IN m_sockAddrto; LRESULT OnReadClose(WPARAM wParam,LPARAM IParam); int socklen; BOOL IsTrue; Msg msg;//收发消息的结构体 UINT m_sport; UINT m_dport; virtual void OnOK(); afx_msg void OnBnClickedStop(); afx_msg void OnBnClickedSend(); };

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/01/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档