基于uCOS-II的UDP网络编程

    技术2026-08-08  6

    基于uCOS-IIUDP网络编程

    ---------------------------------------------------------

    Author             :tiger-johnWebSite            :blog.csdn.net/tigerjb

    Email               jibo.tiger@gmail.com

    开发环境         硬件环境:LPC2200

                                操作系统:UC/OS-II操作系统

                                编译环境:ADS1.2

    Update-Time   : 2011221日星期一

    Tiger声明:本人鄙视直接复制本人文章而不加出处的个人或团体,

    但不排斥别人转载tiger-john的文章,只是请您注明出处并和本人

    联系或留言给我3Q

    ---------------------------------------------------------

    一.    基于UCOS-II操作系统的UDP网络编程

    1.UDP网络编程的组成部分

    Ø  启动任务:负责UDP的初始化,创建通信工具和轮训检测是否有数据报到来。

    Ø  UDP数据处理任务:负责UDP报文的处理

    Ø  UDP服务例程:实现数据的收发。

    二.    启动任务

    1. 启动任务的功能

    l  负责初始化UDP

    l  创建UDP数据处理处理任务和UDP服务例程。

    l  轮训检测是否有数据到来。

    2.UDP初始化由那及部分组成

     

     

    1>初始化网络端口地址

    通过调用SetNetPort()函数来设置主机IP地址网关地址,子网掩码和主机物理地址。

    SetNetPort();

    2>初始化RTL8019芯片

    通过调用InitNic()函数初始化RTL9019以太网芯片对RTL8019芯片的工作寄存器进行设置。

    InitNic(0);

    3>初始化ARP函数

    通过调用Initial_arp()函数初始化ARP

    Initial_arp();

    4>初始化UDP

    通过调用Udp_Initial函数初始化UDP

    Udp_Initial();

    3.启动任务程序

    /********************************************************************

    ** Function name:       TASK0

    ** Descriptions:        创建任务TASK1(udp数据处理任务)TASK2(udp服务例程),分配信号量

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/

    void Task0(void *pdata) 

    {

        UBYTE iii;

        #if OS_CRITICAL_METHOD == 3                         

        OS_CPU_SR  cpu_sr;

           #endif

           TargetInit();         

           OSTaskCreate(Task1,(void *)0, &TaskStk1[1000 - 1],3);

           OSTaskCreate(Task2,(void *)0, &TaskStk2[1000 - 1],4);

           UDP_INIT();

        SetNetPort();

           InitNic(0);                   //RTL8019芯片初始化,global.c中定义

           Initial_arp();

          Udp_Initial();

      while(1)

      {

                 

                  OSTimeDly(4);

                  do

                  {

     

                   iii=Rec_Packet();//监控是否有数据到来

     

                 

                  }

                  while(iii!=0);

        }

    }

     

    三.    UDP服务例程序任务

    1.     UDP服务例程任务的功能:

    Ø  创建套接字

    Ø  绑定本地IP和端口与套接字相连

    Ø  实现数据的接发

    2..UDP服务例程有那几部分组成

    3.UDP服务例程中所用到的API函数接口:

    A.socket()函数

    1)应用程序在使用套接口通信前,必须要拥有一个套接口,使用socket()函数给应用程序创建一个套接口。

    2)函数socket()的原型

    SOCKET * socket(uint16 af,uint16 type,uint16 protocol)该函数功能是从SOCKET pool中分配一个SOCKET插口,供应用程序使用。

    其参数说明如下:1>参数af:表示要使用的协议地址族。

    Ø  PF_INET:

    Ø  AF_INET:

    zlg_socket.h中定义:

    #define PF_INET       0

    #define AF_INET      1

    2>参数type:描述套接口的类型

    Ø  SOCK_STREAM:对应TCP协议

    Ø  SOCK_DGRAM:对应UDP协议

    zlg_socket.h中定义:

    #define SOCK_STREAM 0

    #define SOCK_DGRAM  1

    3>参数protocol:分配SOCKET协议的类型。

    SOCKET协议的类型:

    Ø  TCP_PROTOCOL:表示应用TCP协议和上面的type要一致。

    Ø  UDP_PROTOCOL:表示应用UDP协议和上面的type要一致。

    zlg_socket.h中定义:

    #define TCP_PROTOCOL            0

    #define UDP_PROTOCOL     1

    4>返回值:函数执行成功,返回SOCKET*指针指向的一个SOCKET,失败返回NULL

    3)程序实例:

    s=*socket( 0,SOCK_DGRAM, UDP_PROTOCOL);

    B.bind()函数

    1)socket()函数创建一个套接口后,需要将该套接口与该主机上提供服务的某端口联系在一起。

    2)函数bind()的原型

     int  bind(SOCKET * s,struct  sockaddr * name,uint 16 namelen)

    本函数功能是将IP地址和端口绑定到一个SOCKET 指针* sock指向的s

    其参数说明如下:

    1>SOCKET  * s:指向被绑定的SOCKET,它是socket()函数调用成功时返回的值。

    2>struct sockaddr * name:是一个与指定协议有关的地址结构指针,存储了套接口的地址信息。

    struct  sockaddr{

                     uint16      sin_family;

                     uint8        sin_addr[4];

                     uint16      sin_port;

          };  

    3> namelen:表示地址参数的(name)的长度。

    4>返回值:成功返回值为0

    3)程序实例:

    iii=bind((SOCKET*)&s,(struct sockaddr*)&clientaddr,sizeof(clientaddr));

    C.sendto()函数

    1)对于无连接的套接口,使用sendto()函数来发送一个数据报文。

    2)函数sendto()的原型

    uint16 sendto(SOCKET s,uint8 *buff,uint16 len,int flags,struct  sockaddr  *to,uint16  tolen)

    向指定SOCKET *sock插口发送数据,由UDP使用。

    其参数说明如下:1>SOCKET      s:本地套接字。

    2> uint8 * buff:待发送数据的缓冲区。

    3>uint16  len:指明buf缓冲区中要发送的数据长度。

    4>int flags:调用方式

    5>struct  sockaddr  * to:指明发送数据的目的套接口地址。

    6>uint16  tolen:  to所指的地址长度。

    7>返回值:为发送数据的字节数。

    3)程序实例:

    sendto(s,rec_buffer,10,0, (struct sockaddr*)&servaddr, sizeof(servaddr) );

    D.recvfrom()函数

    1)对于无连接的套接口,通过recvfrom()函数从套接口上接收一个数据报文,并报存发送数据的源地址。

    2)函数recvfrom()的原型

    uint16 recvfrom(SOCKET *s,uint8 *buff,uint16 len,int flags,struct sockaddr * from,uint16 *fromlen)

    函数的参数说明如下:

    1> SOCKET  s :标识一个套接口的描述字。

    2>uint8  * buf:接收数据的缓冲区。

    3>uint16  len:接收数据缓冲区的长度。

    4> int   flags :调用操作方式。

    5>struct  sockaddr  *from: 指明接收数据的目的套接口地址。

    6>uint16       *fromlen:  指向from缓冲区的长度值

    7>返回值:为已读取的字节数。

    3)程序实例:

    recvfrom(s,rev_buffer,100,0,(struct sockaddr*)&serveraddr,&iii);

    E.closesocket()函数

    1)一个套接口不再使用时一定要关闭这个套接口,以释放与该套接口关联的所有资源,包括等候处理的数据。

    2)函数closesocket()函数的原型

    int closesocket( SOCKET s )

    函数参数说明如下:

    1>  SOCKET  s:表示即将被关闭的套接口。

    3)程序的实例:

    closesocket(s )

    4.UDP服务例程的程序:

    /********************************************************************

    ** Function name:       TASK2

    ** Descriptions:        UDP服务例程,实现数据的收发

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/

    void Task2(void *pdata)

    {

     

     uint8 rec_buffer[10];

     uint8 add[20]={"Hello tiger-john!"};

     SOCKET      s;

     int send_coute;

     int rec_coute;

     uint16 iii;

     struct sockaddr servaddr,clientaddr;

     PINSEL1&=0xfffffcff;     //P0.20定以为GPIO是具体情况而定

           OSTimeDly(60);

           servaddr.sin_family=0;

           servaddr.sin_addr[1]=168;

           servaddr.sin_addr[2]=0;

           servaddr.sin_addr[3]=55;

           servaddr.sin_port=1025; 

        OSTimeDly(60);

        s=*socket( 0,SOCK_DGRAM, UDP_PROTOCOL);

        clientaddr.sin_family=0;

           clientaddr.sin_addr[0]=192;

           clientaddr.sin_addr[1]=168;

           clientaddr.sin_addr[2]=0;

           clientaddr.sin_addr[3]=174;

           clientaddr.sin_port=1025; 

           iii=bind( (SOCKET * )&s, (struct sockaddr*)&clientaddr,sizeof(clientaddr));

       while(1)

           {   

             rec_coute = recvfrom(s,rec_buffer,10,0,(struct sockaddr *)&servaddr,&iii);

                  if(rec_coute > 0)

                  {

                         if(rec_buffer[0] == 'A')

                         {

                                //如果接收到的数据首字母是A,则把接收到的数据直接返回

                                send_coute = sendto(s,rec_buffer,rec_coute,0, (struct sockaddr*)&servaddr, sizeof(servaddr) );

                  }

                  else

                  {

                        //否则发送"tiger-john"给上位机

                        send_coute = sendto(s,add,20,0,(struct sockaddr *)&servaddr,sizeof(servaddr));

                  }

              

            }

         }  

    }

    四.完整程序

    情景:接收上位机发送的数据,若上位机发送数据的首字母为A时将接收到的数据再发送给上位机,否则发送tiger-john给上位机。

    /****************************Copyright(c)*******************************

    **                                   西安邮电学院

    **                                   graduate school

    **                                                                  XNMS实验室

    **                                  Author:冀博

    **                                                                  Time:2011221

    **                                 http://blog.csdn.net/tigerjb

    **

    **--------------FileInfo-------------------------------------------------------------------------------

    ****************************Copyright(c)******************************/

     

    #define          MSG_QUEUE_SIZE        20              

    #define           TaskStkLengh          3000

     

    OS_EVENT                *RecPackedFlag;             

    OS_EVENT                *RecBufOverFlowFlag;    

    OS_EVENT                *RecPingPackedFlag;

     

    OS_STK                TaskStk0[TaskStkLengh];  

    OS_STK              TaskStk1[1000];           

    OS_STK              TaskStk2[1000];

     

    void    Task0(void *pdata);               //Task0  任务0

    void    Task1(void *pdata);         //Task1  任务1

    void    Task2(void *pdata);         //Task2  任务2

     

     

    /********************************************************************

    ** Function name:       UDP_INIT

    ** Descriptions:        初始化网络地址,RTL8019ARPUDP

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/

    void UDP_INIT(void )

    {

          

         SetNetPort();

           InitNic(0);                   //RTL8019芯片初始化,global.c中定义

           Initial_arp();

          Udp_Initial();

    }

     

     

    /*********************************************************************

    * Function name:       main()

    ** Descriptions:        创建任务TASK0任务

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/

    int main (void)

    {

        UBYTE iii;

        OSInit();                                         

        OSTaskCreate(Task0,(void *)0, &TaskStk0[TaskStkLengh - 1],2);

         RecPackedFlag=         OSSemCreate(0);

           RecBufOverFlowFlag=      OSSemCreate(0);

           RecPingPackedFlag=  OSSemCreate(0);

           SendFlag=            OSSemCreate(1);

           RecUdpQFlag=           OSQCreate(&RecUdpQ[0],Q_Max_Size);

        OSStart();                                          

    }

    /********************************************************************

    ** Function name:       TASK0

    ** Descriptions:        创建任务TASK1(udp数据处理任务)TASK2(udp服务例程),分配信号量

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/

    void Task0(void *pdata) 

    {

        UBYTE iii;

        #if OS_CRITICAL_METHOD == 3                         

        OS_CPU_SR  cpu_sr;

           #endif

           TargetInit();         

           OSTaskCreate(Task1,(void *)0, &TaskStk1[1000 - 1],3);

           OSTaskCreate(Task2,(void *)0, &TaskStk2[1000 - 1],4);

           UDP_INIT();

        SetNetPort();

           InitNic(0);                   //RTL8019芯片初始化,global.c中定义

           Initial_arp();

          Udp_Initial();

      while(1)

      {

                 

                  OSTimeDly(4);

                  do

                  {

     

                   iii=Rec_Packet();//监控是否有数据到来

     

                 

                  }

                  while(iii!=0);

        }

    }

    /*********************************************************************

    * Function name:       TASK1

    ** Descriptions:        UDP数据处理任务

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/     

    void Task1(void *pdata)

     

    {

        void * UdpTemp;

           uint8 eer;   

        while (1)

        {

                UdpTemp=OSQPend(RecUdpQFlag,0,&eer);

                  if(eer==OS_NO_ERR)

                         {

                  Udp_Process((Rec_Ptr *)UdpTemp);

                  eer=eer;

                         }

           

        }   

    }

    /********************************************************************

    ** Function name:       TASK2

    ** Descriptions:        UDP服务例程,实现数据的收发

    ** input parameters:   

    ** output parameters:  

    ** Returned value:     

    ********************************************************************/

    void Task2(void *pdata)

    {

     

     uint8 rec_buffer[10];

     uint8 add[20]={"Hello tiger-john!"};

     SOCKET      s;

     int send_coute;

     int rec_coute;

     uint16 iii;

     struct sockaddr servaddr,clientaddr;

     PINSEL1&=0xfffffcff;     //P0.20定以为GPIO是具体情况而定

           OSTimeDly(60);

           servaddr.sin_family=0;

           servaddr.sin_addr[1]=168;

           servaddr.sin_addr[2]=0;

           servaddr.sin_addr[3]=55;

           servaddr.sin_port=1025; 

        OSTimeDly(60);

        s=*socket( 0,SOCK_DGRAM, UDP_PROTOCOL);

        clientaddr.sin_family=0;

           clientaddr.sin_addr[0]=192;

           clientaddr.sin_addr[1]=168;

           clientaddr.sin_addr[2]=0;

           clientaddr.sin_addr[3]=174;

           clientaddr.sin_port=1025; 

           iii=bind( (SOCKET * )&s, (struct sockaddr*)&clientaddr,sizeof(clientaddr));

       while(1)

           {   

             rec_coute = recvfrom(s,rec_buffer,10,0,(struct sockaddr *)&servaddr,&iii);

                  if(rec_coute > 0)

                  {

                         if(rec_buffer[0] == 'A')

                         {

                                //如果接收到的数据首字母是A,则把接收到的数据直接返回

     send_coute = sendto(s,rec_buffer,rec_coute,0, (struct sockaddr*)&servaddr, sizeof(servaddr) );

                  }

                  else

                  {

                        //否则发送"tiger-john"给上位机

        send_coute = sendto(s,add,20,0,(struct sockaddr *)&servaddr,sizeof(servaddr));

                  }

              

            }

         }  

    }

     

     
    最新回复(0)