UDP即时通信

编写一个基于某种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();
    
};











原创文章 24 获赞 36 访问量 3万+

猜你喜欢

转载自blog.csdn.net/xuan_lu/article/details/79080088