OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2227|回复: 2

LWIP设置socket为非阻塞模式

[复制链接]

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
839
金钱
839
注册时间
2016-8-23
在线时间
116 小时
发表于 2023-9-20 18:44:37 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 紫气东升 于 2023-9-20 18:45 编辑

在网上查阅,别人发出来的说,可以通过设置SO_NONBLOCK选项来将socket设置为非阻塞模式。但是我从 http://savannah.nongnu.org/projects/lwip/  这个网站下载的lwip2.1.2和lwip2.1.3版本库函数,都没有搜到SO_NONBLOCK这个宏变量。那么我该如何设置非阻塞模式呢?
在创建socket的时候,设置SO_NONBLOCK选项:
int sockfd = lwip_socket(AF_INET, SOCK_STREAM, 0);
int nonblock = 1;
lwip_setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &nonblock, sizeof(nonblock));
————————————————
版权声明:本文为CSDN博主「最后一个bug」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33471732/article/details/129636081

最佳答案

查看完整内容[请看2#楼]

使用以下函数,可以设置非阻塞模式接收数据 bool SetNonBlock(int fd) { int res = 0; int flags = fcntl(fd, F_GETFL, 0); if(flags < 0) { printf("error code: %d, set non block, fcntl get failed\r\n", flags); return pdFALSE; } res = fcntl(fd, F_SETFL, flags | O_NONBLOCK); if(res < 0) { printf("error code: %d, set non block, fcntl ...
天道酬勤
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
839
金钱
839
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2023-9-20 18:44:38 | 显示全部楼层
使用以下函数,可以设置非阻塞模式接收数据
bool SetNonBlock(int fd)
{
    int res = 0;
    int flags = fcntl(fd, F_GETFL, 0);
   
    if(flags < 0)
    {
        printf("error code: %d, set non block, fcntl get failed\r\n", flags);
        return pdFALSE;
    }
    res = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    if(res < 0)
    {
        printf("error code: %d, set non block, fcntl set failed\r\n", res);
        return pdFALSE;
    }
    return pdTRUE;
}
具体使用方法如下:
创建一个任务,创建服务端tcp socket,等待客户端连接。等客户端连接后再创建一个接收网络数据任务
void server_run_task(void *arg)
{
    int ret = 0;
    uint32_t len = 0;
    int tcp_port = 42552;
    struct sockaddr_in svr_addr, clt_addr;
        int opt = 1;
       
   
    while(1)
    {
        /* bind to port 42552 at any interface */
        memset(&svr_addr, 0, sizeof(svr_addr));
        svr_addr.sin_family = AF_INET;
        svr_addr.sin_port = htons(tcp_port);
        svr_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        
        /* create a TCP socket */
        main_sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(main_sockfd < 0)
        {
            printf("socket error\r\n");
            continue;
        }
        
        ret = bind(main_sockfd, (struct sockaddr *)&svr_addr, sizeof(svr_addr));
        if(ret < 0)
        {
            lwip_close(main_sockfd);
            main_sockfd = -1;
            printf("fail to bind\r\n");
            continue;
        }
        
        /* listen for incoming connections (TCP listen backlog = 1) */
        ret = listen(main_sockfd, 1);
        if(ret < 0)
        {
            lwip_close(main_sockfd);
            main_sockfd = -1;
            printf("listen error\r\n");
            continue;
        }
        
        len = sizeof(clt_addr);
        
        /* grab new connection */
        while(1)
        {
            client_1_fd = accept(main_sockfd, (struct sockaddr *)&clt_addr, (socklen_t *)&len);
            printf("accept!:client_1_fd = %d\r\n", client_1_fd);
            if(-1 != client_1_fd)
            {
                printf("\nconnect\n");
                if(CreatRec_result != pdFAIL)
                {
                    if(client_1_fd >= 1)
                    {
                        printf("close front_fd:%d\r\n", front_fd);
                        lwip_close(front_fd);
                    }
                    vTaskDelete(TCPServRec_xTask);
                    CreatRec_result = pdFAIL;
                    printf("delete server receive\r\n");
                }
                front_fd = client_1_fd;
                printf("front_fd=%d\r\n", front_fd);
               
                mdns_resp_announce(&g_mynetif);
                vTaskDelay(5);
                CreatRec_result = xTaskCreate(TCPServerRec, "SERVERREC", DEFAULT_THREAD_STACKSIZE,
                                            (int *)&client_1_fd, SERV_REC_PRIO, &TCPServRec_xTask);
                if(CreatRec_result == pdFAIL)
                {
                    lwip_close(client_1_fd);
                    client_1_fd = -1;
                    continue;
                }
            }
            else
            {
                lwip_close(client_1_fd);
                client_1_fd = -1;
                if(CreatRec_result != pdFAIL)
                {
                    vTaskDelete(TCPServRec_xTask);
                    CreatRec_result = pdFAIL;
                    printf("delete server receive\r\n");
                }
                lwip_close(main_sockfd);
                main_sockfd = -1;
                break;
            }
        }
    }
}

接收网络数据任务,非阻塞模式放在这个函数里设置
void TCPServerRec(void * pvParameters)
{
    int recvNum = 0;
    uint16_t i = 0;
    uint16_t errcount = 0;
    BaseType_t notify_result = pdFALSE;
   
    SetNonBlock(client_1_fd); //set non-blocking mode
   
    while(1)
    {
        vTaskDelay(300);  //delay 300ms
        recvNum = recv(client_1_fd, Netbuf, MAX_BUF_SIZE, 0);
        printf("TCP recv = %d\r\n", recvNum);
        if(recvNum > 0)
        {
            errcount = 0;
            
            for(i=0; i<recvNum; i++)
            {
                Netrecbuf[Rec_offset] = Netbuf[i];

                Rec_offset++;
                if(Rec_offset == MAX_BUF_SIZE)
                {
                    Rec_offset = 0;
                }
            }

            notify_result = xTaskNotifyGive(Buffer_parse_xTask);
            if(notify_result != pdPASS)
            {
                printf("Notify fail\n");
            }
        }
        else
        {
            if((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
            {
                errcount = 0;
                continue;
            }
            errcount++;
            if(errcount >= 10)
            {
                printf("recv error:%d, close normally\r\n", errno);
                errcount  = 0;
                lwip_close(client_1_fd);
                client_1_fd = -1;
                CreatRec_result = pdFAIL;
                vTaskDelete(NULL);
            }
        }
    }
}
天道酬勤
回复

使用道具 举报

58

主题

6291

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11406
金钱
11406
注册时间
2014-4-1
在线时间
1282 小时
发表于 2023-10-17 12:43:51 | 显示全部楼层

不懂,非阻塞模式是怎么回事?有什么优点?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 07:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表