MFC的UDP编程实现[通俗易懂]

MFC的UDP编程实现[通俗易懂]1、编程原理UDP是面向非连接的通信协议,比TCP协议简单很多。无论是服务器端还是客户端,其通信过程概括为:创建套接字(socket)–>绑定(bind)–>发送send(或接收recv)–>关闭套接字(closesocket) 2、特殊地址:在实际通信网络中,我们几乎不会用到“0.0.0.0″和“127.0.0.1”这样的IP地址。但是在一台计算机上,特别用于某些测试用

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1、编程原理

UDP是面向非连接的通信协议,比TCP协议简单很多。无论是服务器端还是客户端,其通信过程概括为:

创建套接字(socket)–>绑定(bind)–>发送send(或接收recv)–>关闭套接字(closesocket

 

2、特殊地址:

在实际通信网络中,我们几乎不会用到“0.0.0.0″和“127.0.0.1”这样的IP地址。但是在一台计算机上,特别用于某些测试用途时,这类地址就有用武之地了。

(1)环回地址:127.0.0.1,该地址可用于本地计算机测试接收功能,即本地计算机绑定一IP地址(如192.168.1.2)时,可向环回地址发送信息M,则本地计算机可收到“反馈”回来的同样信息M(具有服务端性质)

(2)全零网络地址:0.0.0.0,可作为源地址,表示整个网络,即“任意地址”

3、重要函数

(1)创建套接字函数socket()

函数原型:SOCKET PASCAL FAR socket( int af, int type, int protocol);

返回值说明:成功返回套接字,失败返回INVALID_SOCKET;

创建流套接字(TCP)时,如:m_socket = socket(AF_INET,SOCK_STREAM,0)

创建数据报套接字(UDP),如:m_socket = socket(AF_INET,SOCK_DGRAM,0)

在成功创建套接字之后,需要填充sockaddr_in结构体作为网络函数参数:

struct sockaddr_in

   {

      shortint sin_family;//地址协议

     unsigned short int sin_port;//端口号

     struct in_addr sin_addr;//IP地址

     unsigned char sin_zero[8];// sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。

    }

如在VS2010中,有:

//SOCKADDR_INaddrSock;//SOCKADDR_INsockadd_in的宏定义,此变量在头文件中定义

((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS2))->GetAddress(sourceIP);//获取控件上IP地址

addrSock.sin_family=AF_INET;

addrSock.sin_port=htons(6000);

addrSock.sin_addr.S_un.S_addr=htonl(sourceIP);//sourceIP表示运行该程序的主机IP

 

(2)绑定函数bind()

函数原型:int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR *name,int namelen)

返回值说明:绑定成功,返回0值,否则返回-1SOCKET_ERROR

如:

int retval

retval = bind(m_socket,(SOCKADDR*)&addrSock, sizeof(SOCKADDR))//SOCKADDRsockaddr的宏定义

*3)创建线程函数CreateThread()

创建线程后,立即开启,调度线程函数:

RECVPARAM *pRecvParam=newRECVPARAM;

pRecvParam->sock=m_socket;

pRecvParam->hwnd=m_hWnd;

HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);//RecvProc为线程函数

CloseHandle(hThread);

 

//线程函数

DWORD WINAPICMyChatDlg::RecvProc(LPVOIDlpParameter)

{

//lpParmeter为创建线程是所提交的函数参数

    SOCKETsock=((RECVPARAM*)lpParameter)->sock;

    HWNDhwnd=((RECVPARAM*)lpParameter)->hwnd;

    deletelpParameter; //释放对象

SOCKADDR_IN addrFrom;

    int len=sizeof(SOCKADDR);

    char recvBuf[200];

    char tempBuf[300];

    int retval;

    while(TRUE)   //创建线程的必要性

    {

    retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);//获取套接字接收内容

        if(SOCKET_ERROR==retval)

            break;

        sprintf(tempBuf,”%s说: %s”,inet_ntoa(addrFrom.sin_addr),recvBuf);

 

        ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);//提交消息,触发消息响应

    }

    return 0;

}

分析:

struct RECVPARAM

{

    SOCKET sock;

    HWND hwnd;

};//在头文件中定义该结构体

 

线程的创建是通过函数CreateThread来实现的,调用成功返回句柄和一个id。

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes,  //线程的安全属性,NULL为缺省值

DWORD dwStackSize,                        //线程堆栈的大小,0为系统缺省值

LPTHREAD_START_ROUTINE lpStartAddress,  //线程函数的起始地址可为线程函数名

LPVOID lpParameter,                      //传递给线程函数的参数,重要!

DWORD dwCreationFlags,              //线程创建后是否立即启动,0表示立即启动

LPDWORD lpThreadId                     //线程的ID号

);

(4)获取接收信息的recvfrom函数(经socket接收数据):

函数原型:ssize_trecvfrom(int sockfd,void *buf,int len,unsigned int flags, struct sockaddr*from,socket_t *fromlen);

参数含义详见:http://baike.baidu.com/view/1744189.htm

功能描述:该函数接收来自套接字的数据,数据存到缓冲区,并从sockaddr中可读取到相关网络参数(如接收数据的源地址等)

 

(5)发送函数函数sendto()

函数原型:intPASCAL FAR sendto (

IN SOCKET s,

IN const char FAR *buf,

IN int len,

IN int flags,

IN const structsockaddr FAR *to,

IN int tolen);

如:sendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));

4、关键点:

(1)UDP实现过程简单,关键是了解每个过程所需要函数及其使用方法

(2)为UDP通信创建线程,是设计更加合理

(3)套接字创建之后很重要的一步是填充sockaddr_in,绑定的成功与否与该结构体具有紧密的关系。

(4)如果是基于人机交互的实现模式,UDP通信之前的工作可以分成几个模块,而这些模块,注意要共用一个套接字(如在类中定义一个SOCKET变量)。如果有默认式的UDP通信模式,可以将UDP通信之前的工作放在一起,即定义一个initial函数,将这些过程全放进去即可。

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/196203.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 伊甸园_绿田园农业

    伊甸园_绿田园农业近日,经国务院批复,《全国高标准农田建设规划(2021-2030年)》(以下简称《规划》)正式印发实施。《规划》指出,到2035年,通过持续改造提升,全国高标准农田保有量和质量进一步提高,绿色农田、数字农田建设模式进一步普及,支撑粮食生产和重要农产品供给能力进一步提升,形成更高层次、更有效率、更可持续的国家粮食安全保障基础。《规划》要求利用数字技术,推动农田建设、生产、管护相融合,提高全要素生产效率。重点推进物联网、大数据、移动互联网、智能控制、卫星定位等信息技术在农田建设中的应用,配套耕地质量综合监测点

    2022年10月21日
    3
  • MongoDB高级操作(管道聚合)

    MongoDB高级操作(管道聚合)一、 聚合aggregate聚合(aggerate)主要用于计算数据,类似于SQL中的sum(),avg(),聚合aggregate是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。方法:db.stu.aggergate({管道:{表达式}}),如图:二、管道(grep)在Mon…

    2025年8月4日
    2
  • php用哪个版本_php什么版本好

    php用哪个版本_php什么版本好一. PHP5.2、5.3、5.4、5.5、5.6版本区别对比以及新功能详解1.php5.2以前1.1autoload的使用;当在代码中使用一个未定义的类的时候,该函数就会被调用

    2022年8月2日
    7
  • 今儿下午疲惫极了_形容疲惫至极的诗句

    今儿下午疲惫极了_形容疲惫至极的诗句回家的公车上人也特别的多,春天来了,气温渐温,街上的颜色也丰富起来,我一路的走,一路的观望,看着一张张的笑脸,我也一路的想,想我爱的人和爱我的人,不觉得走神了。下车没两步,我摔了一交,结结实实的。手中的电脑包抛了老远,我一下子倒在了路边,脑子嗡响了一下,暂时的记忆就没了。大约有那么两三秒,也许是我摔倒的动静太大了,感觉周围的目光都在朝我这边看,一时间的尴尬,没顾得上身上的土,站起来就往住的方向猛走

    2026年1月17日
    5
  • go语言实现最小区块链教程7-网络「建议收藏」

    go语言实现最小区块链教程7-网络「建议收藏」1介绍Introduction到目前为止,我们构建了一个含有以下特征的区块链:匿名、安全、以及随机产生地址;区块链数据存储;PoW系统;可靠的交易记录存储方式。这些特征都非常关键,但是这还不够。能够让这些特征升华的,并且让加密货币变得可能的,是网络(network)。这样的区块链实现如果只能在单一的电脑上面运行有什么用?这些基础加密特性有什么有,如果仅有一个用户?网络让这些机制工作并发挥作用。…

    2022年5月28日
    45
  • java 内部类 静态方法调用_内部类和静态内部类的调用「建议收藏」

    java 内部类 静态方法调用_内部类和静态内部类的调用「建议收藏」packageday6$6;publicclassInside{publicstaticvoidmain(String[]args){//先创建一个外部类对象Outsidein=newOutside();//在通过外部类对象创建一个内部类对象Outside.Indooroi=in.newIndoor();//调用内部类自己的属性和方法oi.Swim();System…

    2022年10月11日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号