CH32V307,DHCP模式下,创建UDPserver,报错。

如题,要创建一个UDP server,在系统初始化时先进行网络初始化,两种方式,一种是静态IP,一种是动态IP。


静态IP时,在主函数中直接调用WCHNET_CreateUdpSocket创建UDP服务,能够成功;

动态IP时,在回调WCHNET_DHCPCallBack中创建UDP服务,报错 0x11 (WCHNET_ERR_MEM)


在上述两个位置创建tcpClient,均能成功。


代码如下,main函数在例程的基础上加了一个静态/动态IP的分支选择。

修改帖子,代码显示有问题,?3楼重贴代码。


WCHNET_CreateUdpSocket 用的是例程中的代码,不知是否要补充参数。


/*********************************************************************
 * @fn      WCHNET_CreateUdpSocket
 *
 * @brief   Create UDP Socket
 *
 * @return  none
 */
void WCHNET_CreateUdpSocket(void)
{
    u8 i;
    SOCK_INF TmpSocketInf;
    memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF));
    TmpSocketInf.SourPort = udpServerPort;
    TmpSocketInf.ProtoType = PROTO_TYPE_UDP;
    TmpSocketInf.RecvStartPoint = (u32) SocketRecvBuf;
    TmpSocketInf.RecvBufLen = UDP_RECE_BUF_LEN;
    TmpSocketInf.AppCallBack = WCHNET_UdpServerRecv;
    i = WCHNET_SocketCreat(&UDPSocketId, &TmpSocketInf);
    printf("UDP:WCHNET_SocketCreat %d\r\n", UDPSocketId);
    mStopIfError(i);
}



void main(){
      ......
                
    WCHNET_DHCPSetHostname("WCHNET");             //Configure DHCP host name
    i = ETH_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr);   //Ethernet library initialize
    mStopIfError(i);
    if(i == WCHNET_ERR_SUCCESS)
        printf("WCHNET_LibInit Success\r\n");
        
    if(IPAddr[0]){
        // 静态ip地址
        // 创建udp服务, 这里创建UDP服务能够成功。在这里创建TCPClient也能成功
        WCHNET_CreateUdpSocket();   
    }else {
        //Start DHCP 动态IP
        WCHNET_DHCPStart(WCHNET_DHCPCallBack);
    }
    
    ....
}
u8 WCHNET_DHCPCallBack(u8 status, void *arg)
{
    u8 *p;
    u8 tmp[4] = {0, 0, 0, 0};
    if(!status)
    {
        p = arg;
        printf("DHCP Success\r\n");
        /*If the obtained IP is the same as the last IP, exit this function.*/
        if(!memcmp(IPAddr, p ,sizeof(IPAddr)))
            return READY;
        /*Determine whether it is the first successful IP acquisition*/
        if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){
            /*The obtained IP is different from the last value,
             * then disconnect the last connection.*/
            WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
        }
        memcpy(IPAddr, p, 4);
        memcpy(GWIPAddr, &p[4], 4);
        memcpy(IPMask, &p[8], 4);
        printf("IPAddr = %d.%d.%d.%d \r\n", (u16)IPAddr[0], (u16)IPAddr[1],
               (u16)IPAddr[2], (u16)IPAddr[3]);
        printf("GWIPAddr = %d.%d.%d.%d \r\n", (u16)GWIPAddr[0], (u16)GWIPAddr[1],
               (u16)GWIPAddr[2], (u16)GWIPAddr[3]);
        printf("IPMask = %d.%d.%d.%d \r\n", (u16)IPMask[0], (u16)IPMask[1],
               (u16)IPMask[2], (u16)IPMask[3]);
        printf("DNS1: %d.%d.%d.%d \r\n", p[12], p[13], p[14], p[15]);
        printf("DNS2: %d.%d.%d.%d \r\n", p[16], p[17], p[18], p[19]);
        
        //创建udp服务
        //  这里创建UDP服务报错0x11。WCHNET_ERR_MEM, out of memory error. 
        //  在这里创建TCPClient能成功
        WCHNET_CreateUdpSocket();  
        
        return READY;
    }
    else
    {
        printf("DHCP Fail %02x \r\n", status);
        /*Determine whether it is the first successful IP acquisition*/
        if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){
            /*The obtained IP is different from the last value*/
            WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
        }
        return NoREADY;
    }
}




您好,我这边通过分配动态ip创建UDP是正常的,附上测试程序,您可以测试一下,看您的报错,是内存溢出,可能是创建的socket数量超出定义导致,您可以将您的工程发我邮箱,我帮您看下,后续有问题可通过邮箱联系:kx@wch.cn

image.png

icon_rar.gifDHCP-UDP.zip



收到,多谢。我先测试一下。


@TECH_Kx

您发过来的例子,已跑通,能够建立起udp服务,但具体的应用还有几个问题需再确认一下:


1、您给的例子中,在创建UDPServer时就指定了客户端IP地址与端口,只有指定的客户端(包括IP和端口)发服务器发送数据才有应答。这种方式满足不了实际需求;


2、系统提供的UDPServer例子中(net version:16),用到了回调函数, TmpSocketInf.AppCallBack = WCHNET_UdpServerRecv,可以接收任意客户端发过来的数据并响应;  您给的例子中(net version:17),对数据的处理是在WCHNET_DataLoopback中实现的,但我没version17实现这种回调。 


下面的代码,是我在您基础上增加了一个函数、一条语句,没跑通。

// 这个函数是从系统Exam的UDPServer中复制过来的 (net version: 16)
void WCHNET_UdpServerRecv(struct _SCOK_INF *socinf, u32 ipaddr, u16 port, u8 *buf, u32 len)
{
    u8 ip_addr[4], i;
    printf("Remote IP:");
    for (i = 0; i < 4; i++) {
        ip_addr[i] = ipaddr & 0xff;
        printf("%d ", ip_addr[i]);
        ipaddr = ipaddr >> 8;
    }
    printf("srcport = %d len = %d socketid = %d\r\n", port, len,
            socinf->SockIndex);
    WCHNET_SocketUdpSendTo(socinf->SockIndex, buf, &len, ip_addr, port);
}

/*********************************************************************
 * @fn      WCHNET_CreateUdpSocket
 *
 * @brief   Create UDP Socket
 *
 * @return  none
 */
void WCHNET_CreateUdpSocket(void)
{
    u8 i;
    SOCK_INF TmpSocketInf;
    memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF)); // 作为服务端,应该是不需要指定客户端ip、port的
    memcpy((void *) TmpSocketInf.IPAddr, DESIP, 4);      // 但不指定desip/desport,会输出“TCP Disconnect”
    TmpSocketInf.DesPort = desport;                      //   且客户端发送数据过来,会输出“HardFault_Handler”(仅一次) 
    TmpSocketInf.SourPort = srcport;
    TmpSocketInf.ProtoType = PROTO_TYPE_UDP;
    TmpSocketInf.RecvStartPoint = (u32) SocketRecvBuf[SocketId];
    TmpSocketInf.RecvBufLen = UDP_RECE_BUF_LEN;
    TmpSocketInf.AppCallBack = WCHNET_UdpServerRecv; // 加了这一句,用于回调,没有成功
    i = WCHNET_SocketCreat(&SocketId, &TmpSocketInf);
    printf("WCHNET_SocketCreat %d\r\n", SocketId);
    mStopIfError(i);
}



icon_rar.gifEXAM-DHCP-UDPServer.zip


报错源码。


问题解决,感谢!


ETH例程每创建一个TCP或者UDP的时候是需要在netconfig.h中增加响应的数量,如上图,因为DHCP本身是采用的UDP协议,所以DHCP例程中WCHNET_NUM_UDP的数量为1,这就是为什么当您关闭DHCP的时候,创建UDP是可以的,当您开启DHCP的时候,由于DHCP已经占用这个UDPsocket,所以您再创建UDP就会显示溢出缓冲区的错误(缓冲区是依据socket的数量来创建的),如果您想在开启DHCP的情况下创建UDP则需要将WCHNET_NUM_UDP的数量改为2,如果您想创建两个UDP,则改完3,意思就是每多创建一个就要增加一个数量,创建TCP也是如此,


只有登录才能回复,可以选择微信账号登录