VS2012 MFC UDP通信

本工具设计的目的是用于自己项目上,由于好久没有使用C++了,可能编程有些丑陋,哪里不对希望大家见谅。本文参考了许多前辈的例子,终于搞好了。若有和前辈们相同的地方,可以联系我,进行删除。本意也是大家互相学习嘛,废话不多说了,看图:

由于是我们项目专用的工具,端口目前是固定写死在程序中的,有需要的可以自己进行添加。

创建连接

void CMFCUDPDlg::OnClickedButtonCreateSocket()
{
    // TODO: 在此添加控件通知处理程序代码
    CString temp;
    m_createsocket.GetWindowText(temp);///获取按钮的文本
    UpdateData(true);
    if(temp == _T("关闭连接"))///表示点击后是"关闭串口",也就是已经关闭了串口
    {
        //关闭socket        
        m_createsocket.SetWindowText(_T("打开连接"));///设置按钮文字为"打开串口"
        //关闭接收线程,关闭socket
        CloseListenTread();
        closesocket(m_socket);
    }
    else if(temp == _T("打开连接"))///当前列表的内容个数
    {
        UpdateData(true);
        m_socket = socket(AF_INET, SOCK_DGRAM, 0);
        if( INVALID_SOCKET  == m_socket )
        {
           AfxMessageBox(_T("创建套接字失败"));
           return;
        }
        else
        {
            SOCKADDR_IN addr;
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
            //addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
            addr.sin_family = AF_INET;
            addr.sin_port = htons(6000);
            int retval;
            retval = bind(m_socket, (SOCKADDR*)&addr, sizeof(SOCKADDR));
            if (SOCKET_ERROR == retval)
            {
                AfxMessageBox(_T("绑定失败!"));
                closesocket(m_socket);
                return ;
            }
            //创建接收线程
            if (!OpenListenThread())  
            {  
                AfxMessageBox(_T("错误,请关闭应用,重新打开!"));
            }
            m_createsocket.SetWindowText(_T("关闭连接"));
        }        
    }
}
 

发送数据:

void CMFCUDPDlg::OnClickedButtonSendMessage()
{
    // TODO: 在此添加控件通知处理程序代码
    GetDlgItem(IDC_BUTTON_SEND)->SetFocus();
    CString temp;
    int i=0;
    UpdateData(true);
    m_createsocket.GetWindowText(temp);
    if (temp == "打开连接")///没有打开串口
    {
        AfxMessageBox(_T("请首先打开连接"));
        return;
    }
    
    m_sendmessage.GetWindowText(temp);
    size_t len = _tcsclen(temp) + 1;
    char* m_str = NULL;
    size_t* converted = 0;
    m_str = new char[len];
#ifdef UNICODE
    wcstombs_s(converted, m_str, len, temp.GetBuffer(0), _TRUNCATE);
#else
    m_str = temp.GetBuffer(0);
#endif

    DWORD dwIP;
    m_hostip.GetAddress(dwIP);
    SOCKADDR_IN addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(hostport);
    addr.sin_addr.s_addr = htonl(dwIP);
    sendto(m_socket, m_str, strlen(m_str), 0, (SOCKADDR*)&addr, sizeof(SOCKADDR));

    m_sendmessage.SetSel(0, -1);
    m_sendmessage.Clear();//清空数据
    m_sendmessage.GetFocus();//再次获得焦点
    UpdateData(FALSE);//必须的。否则界面内容不更新改变
}

接收数据是放在另外一个线程中进行处理

UINT WINAPI CMFCUDPDlg::RecvThreadProc(LPVOID lpParameter)
{
    //AfxMessageBox(_T("线程工作"));
    /** 得到本类的指针 */
    CMFCUDPDlg *pRecvMessage = reinterpret_cast<CMFCUDPDlg*>(lpParameter);

    SOCKADDR_IN ClntAddr; 
    int clntAddrLen = sizeof(ClntAddr);
    char echoBuffer[1024]=""; 
    CString buffer;
    int recvMsgSize  = 0;
    size_t len = 0;
    size_t converted = 0;
    //处理数据的接收
    if(!s_bExit)//表示线程已经开启,正在工作,这句代码可以不要,下面的while有判断
    {        
        while(!s_bExit)
        {
            //一直阻塞到有客户端发来数据 (sock, recvBuf, 200, 0, (SOCKADDR*)&addr, &len);
            recvMsgSize = recvfrom(pRecvMessage->m_socket,echoBuffer,sizeof(echoBuffer),0 ,(SOCKADDR*)&ClntAddr, &clntAddrLen);
            if (SOCKET_ERROR == recvMsgSize)
            {
                //AfxMessageBox(_T("断开连接,请重新打开连接"));
                break;
            }
 
             //把echoBuffer转格式成wchar_t
            len = strlen(echoBuffer) + 1;
            wchar_t *WStr;
            WStr=(wchar_t*)malloc(len*sizeof(wchar_t));
            mbstowcs_s(&converted, WStr, len, echoBuffer, _TRUNCATE);
  
            //获取对方ip
            char *addr = inet_ntoa(ClntAddr.sin_addr);
            //把addr转格式成wchar_t
            len = strlen(addr) + 1;
            wchar_t *address;
            address=(wchar_t*)malloc(len*sizeof(wchar_t));
            mbstowcs_s(&converted, address, len, addr, _TRUNCATE);
 
            /*把发送端的ip地址和消息还有换行都存放在buffer里,然后一直往save里追加*/
            buffer.Format(_T("【%s】说 :%s\r\n"),address,WStr);
             
            pRecvMessage->m_recvmessage.SetSel(-1, -1);
            pRecvMessage->m_recvmessage.ReplaceSel(buffer);
        }
    }
    return 0;
}

工程代码中也有一些对线程的管理,以及对控件大小随着主对话框大小改变的处理。

下载地址:https://download.csdn.net/download/lionmon82/10732605

第一次发博客,哪里做的不好多见谅。

本文参考了前辈们的例程,若有侵权,请联系我删除。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值