RT-Thread-packages / wiznet

WIZnet TCP/IP chips (such as W5500/W5100..) SAL framework implement.
Apache License 2.0
49 stars 35 forks source link

当发送数据超过发送缓存 应分包发送保证所有数据发送出去 #58

Open sheepsleep opened 3 years ago

sheepsleep commented 3 years ago

https://github.com/RT-Thread-packages/wiznet/blob/6cf871aec85b3a8e95d4871b6afb5eb0766735b3/ioLibrary/Ethernet/wizchip_socket.c#L533

建议写成循环分包发送 比如用户要发送5k数据 那么分三包发送 2K 2K 1K 这样顶层api调用才不会出问题,WEBNET顶层发送数据缓存4k 调用该wiznet 数据发送API时永远发送不成功 浏览器等待后续的数据导致卡死 freesize = getSn_TxMAX(sn); if (len > freesize) len = freesize; // check size not to exceed MAX size. 超过了缓存大小就分包发送

xiangxistu commented 3 years ago

我感觉,可以通过修改

int wiz_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
{
    struct wiz_socket *sock = RT_NULL;
    uint8_t socket_state = 0;
    int32_t send_len = 0;

    /* check WIZnet initialize status */
    WIZ_INIT_STATUS_CHECK;

    if (data == RT_NULL || size == 0)
    {
        LOG_E("WIZnet sendto input data or size error!");
        return -1;
    }

    sock = wiz_get_socket(socket);
    if (sock == RT_NULL)
    {
        return -1;
    }

    socket_state = getSn_SR(socket);
    switch (sock->type)
    {
    case Sn_MR_TCP:
    {
        if (socket_state == SOCK_CLOSED)
        {
            return 0;
        }
        else if (socket_state != SOCK_ESTABLISHED)
        {
            LOG_E("WIZnet send failed, get socket(%d) register state(%d) error.", socket, socket_state);
            return -1;
        }

        if ((send_len = wizchip_send(socket, (uint8_t *)data, size)) < 0)
        {
            LOG_E("WIZnet socket(%d) send data failed(%d).", socket, send_len);
            return -1;
        }
        break;
    }

    case Sn_MR_UDP:
    case Sn_MR_IPRAW:
    {
        ip_addr_t remote_addr;
        uint16_t remote_port = 0;
        uint8_t ipstr[4] = {0};

        if (socket_state != SOCK_UDP && socket_state != SOCK_IPRAW)
        {
            LOG_E("WIZnet sendto failed, get socket(%d) register state(%d) error.", socket, socket_state);
            return -1;
        }

        if (to)
        {
            socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port);
            ipaddr_to_ipstr(to, ipstr);
        }
        else if (sock->remote_addr)
        {
            socketaddr_to_ipaddr_port(sock->remote_addr, &remote_addr, &remote_port);
            ipaddr_to_ipstr(sock->remote_addr, ipstr);
        }

        if ((send_len = wizchip_sendto(socket, (uint8_t *)data, size, ipstr, remote_port)) < 0)
        {
            LOG_E("WIZnet socket(%d) send data failed(%d).", socket, send_len);
            return -1;
        }
        break;
    }

    default:
        LOG_E("WIZnet socket (%d) type %d is not support.", socket, sock->type);
        return -1;
    }

    return send_len;
}

这个函数,sendto 没有发送足够的数据长度,或许可以在这里进行分片传输;

sheepsleep commented 3 years ago

我感觉,可以通过修改

int wiz_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
{
    struct wiz_socket *sock = RT_NULL;
    uint8_t socket_state = 0;
    int32_t send_len = 0;

    /* check WIZnet initialize status */
    WIZ_INIT_STATUS_CHECK;

    if (data == RT_NULL || size == 0)
    {
        LOG_E("WIZnet sendto input data or size error!");
        return -1;
    }

    sock = wiz_get_socket(socket);
    if (sock == RT_NULL)
    {
        return -1;
    }

    socket_state = getSn_SR(socket);
    switch (sock->type)
    {
    case Sn_MR_TCP:
    {
        if (socket_state == SOCK_CLOSED)
        {
            return 0;
        }
        else if (socket_state != SOCK_ESTABLISHED)
        {
            LOG_E("WIZnet send failed, get socket(%d) register state(%d) error.", socket, socket_state);
            return -1;
        }

        if ((send_len = wizchip_send(socket, (uint8_t *)data, size)) < 0)
        {
            LOG_E("WIZnet socket(%d) send data failed(%d).", socket, send_len);
            return -1;
        }
        break;
    }

    case Sn_MR_UDP:
    case Sn_MR_IPRAW:
    {
        ip_addr_t remote_addr;
        uint16_t remote_port = 0;
        uint8_t ipstr[4] = {0};

        if (socket_state != SOCK_UDP && socket_state != SOCK_IPRAW)
        {
            LOG_E("WIZnet sendto failed, get socket(%d) register state(%d) error.", socket, socket_state);
            return -1;
        }

        if (to)
        {
            socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port);
            ipaddr_to_ipstr(to, ipstr);
        }
        else if (sock->remote_addr)
        {
            socketaddr_to_ipaddr_port(sock->remote_addr, &remote_addr, &remote_port);
            ipaddr_to_ipstr(sock->remote_addr, ipstr);
        }

        if ((send_len = wizchip_sendto(socket, (uint8_t *)data, size, ipstr, remote_port)) < 0)
        {
            LOG_E("WIZnet socket(%d) send data failed(%d).", socket, send_len);
            return -1;
        }
        break;
    }

    default:
        LOG_E("WIZnet socket (%d) type %d is not support.", socket, sock->type);
        return -1;
    }

    return send_len;
}

这个函数,sendto 没有发送足够的数据长度,或许可以在这里进行分片传输;

是的 我就是在这里修改的 分包发送 每次发送前先判断是否在sending 空闲则发送

sheepsleep commented 3 years ago

` if(size>2048) { send_cnt=size/2048; for(send_index=0;send_index<send_cnt;send_index++){ //LOG_D("###WIZnet wiz_sendto called send data len=%d",2048);

            while ((send_len = wizchip_send(socket, (uint8_t *)(data+send_offset), 2048))== 0)
              {

              }
            if(send_len<0)
                {
                   LOG_E("WIZnet socket(%d) send data failed(%d).", socket, 2048);
                   return -1;
                }
            send_offset+=2048;
        }
        if((size%2048)>0){
            //LOG_D("###WIZnet wiz_sendto called send data len=%d",size%2048);

            while ( (send_len =wizchip_send(socket, (uint8_t *)(uint8_t *)(data+send_offset), size%2048)) == 0)
                  {
                    //LOG_D("###WIZnet busy2");
                  }
            if(send_len<0)
            {
                LOG_E("WIZnet socket(%d) send data failed(%d).", socket,  size%2048);
                return -1;
            }
        }
    }else{
         // LOG_D("###WIZnet wiz_sendto called send data len=%d",size);
            if ((send_len =wizchip_send(socket, (uint8_t *)data, size)) < 0)
               {
                   LOG_E("WIZnet socket(%d) send data failed(%d).", socket, size);
                   return -1;
               }
    }`
xiangxistu commented 3 years ago

` if(size>2048) { send_cnt=size/2048; for(send_index=0;send_index<send_cnt;send_index++){ //LOG_D("###WIZnet wiz_sendto called send data len=%d",2048);

            while ((send_len = wizchip_send(socket, (uint8_t *)(data+send_offset), 2048))== 0)
              {

              }
            if(send_len<0)
                {
                   LOG_E("WIZnet socket(%d) send data failed(%d).", socket, 2048);
                   return -1;
                }
            send_offset+=2048;
        }
        if((size%2048)>0){
            //LOG_D("###WIZnet wiz_sendto called send data len=%d",size%2048);

            while ( (send_len =wizchip_send(socket, (uint8_t *)(uint8_t *)(data+send_offset), size%2048)) == 0)
                  {
                    //LOG_D("###WIZnet busy2");
                  }
            if(send_len<0)
            {
                LOG_E("WIZnet socket(%d) send data failed(%d).", socket,  size%2048);
                return -1;
            }
        }
    }else{
         // LOG_D("###WIZnet wiz_sendto called send data len=%d",size);
            if ((send_len =wizchip_send(socket, (uint8_t *)data, size)) < 0)
               {
                   LOG_E("WIZnet socket(%d) send data failed(%d).", socket, size);
                   return -1;
               }
    }`

修改后结果如何?通过的话,可以提交一个 PR 吗?